mirror of https://github.com/llvm/circt.git
1989 lines
77 KiB
Plaintext
1989 lines
77 KiB
Plaintext
; RUN: circt-translate -import-firrtl -verify-diagnostics -split-input-file %s | circt-opt | FileCheck %s
|
|
|
|
FIRRTL version 4.0.0
|
|
circuit MyModule : ; CHECK: firrtl.circuit "MyModule" {
|
|
|
|
; CHECK-LABEL: firrtl.module @MyModule(in %in: !firrtl.uint<8>, out %out: !firrtl.uint<8>) {
|
|
public module MyModule : @[FooBar.scala 369:27]
|
|
input in: UInt<8>
|
|
output out: UInt<8>
|
|
|
|
; CHECK: firrtl.matchingconnect %out, %in : !firrtl.uint<8>
|
|
connect out, in
|
|
|
|
; CHECK: }
|
|
|
|
|
|
; CHECK-LABEL: firrtl.module private @circuit(in %in: !firrtl.uint<80>) {
|
|
module circuit : ; Module with a keyword id.
|
|
input in: UInt<80>
|
|
|
|
; CHECK: }
|
|
|
|
; CHECK-LABEL: firrtl.extmodule private @MyExtModule(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
|
; CHECK: attributes {defname = "myextmodule"}
|
|
; CHECK-NOT: {
|
|
extmodule MyExtModule :
|
|
input in: UInt<8>
|
|
output out : UInt<8>
|
|
defname = myextmodule
|
|
|
|
; CHECK-LABEL: firrtl.extmodule private @MyParameterizedExtModule
|
|
; CHECK-SAME: <FORMAT: none = "xyz_timeout=%d\0A",
|
|
; CHECK-SAME: DEFAULT: ui32 = 0,
|
|
; CHECK-SAME: WIDTH: ui32 = 32,
|
|
; CHECK-SAME: DEPTH: f64 = 3.242000e+01>
|
|
; CHECK-SAME: (in in: !firrtl.uint<8>,
|
|
; CHECK-SAME: out out: !firrtl.uint<8>)
|
|
; CHECK-SAME: attributes {defname = "name_thing"}
|
|
; CHECK-NOT: {
|
|
extmodule MyParameterizedExtModule :
|
|
input in: UInt<8>
|
|
output out: UInt<8>
|
|
defname = name_thing
|
|
parameter FORMAT = "xyz_timeout=%d\n"
|
|
parameter DEFAULT = 0
|
|
parameter WIDTH = 32
|
|
parameter DEPTH = 32.42
|
|
|
|
; Check that integers are extended to 32 bits if they are smaller.
|
|
; CHECK-LABEL: firrtl.extmodule private @IntegerParamsModule
|
|
extmodule IntegerParamsModule :
|
|
; CHECK-SAME: a: ui32 = 1
|
|
parameter a = 1
|
|
; CHECK-SAME: b: ui40 = 4294967296
|
|
parameter b = 4294967296
|
|
|
|
; Module to test type parsing.
|
|
|
|
; CHECK-LABEL: firrtl.module private @types(
|
|
module types :
|
|
input c: Clock ; CHECK: %c: !firrtl.clock,
|
|
input r: Reset ; CHECK: %r: !firrtl.reset,
|
|
input ar: AsyncReset ; CHECK: %ar: !firrtl.asyncreset,
|
|
input a: Analog ; CHECK: %a: !firrtl.analog,
|
|
input a8: Analog<8> ; CHECK: %a8: !firrtl.analog<8>,
|
|
input s: SInt ; CHECK: %s: !firrtl.sint,
|
|
input s4: SInt<4> ; CHECK: %s4: !firrtl.sint<4>,
|
|
input u: UInt ; CHECK: %u: !firrtl.uint,
|
|
input bf: { flip int_1 : UInt<1>, int_out : UInt<2>}
|
|
; CHECK: %bf: !firrtl.bundle<int_1 flip: uint<1>, int_out: uint<2>>
|
|
|
|
input vec: UInt<1>[4] ; CHECK: %vec: !firrtl.vector<uint<1>, 4>) {
|
|
|
|
|
|
; CHECK-LABEL: firrtl.module private @stmts(
|
|
module stmts :
|
|
input reset : UInt<1> ; CHECK: in %reset: !firrtl.uint<1>,
|
|
input reset_async: AsyncReset ; CHECK: in %reset_async: !firrtl.asyncreset,
|
|
input reset_abstract: Reset ; CHECK: in %reset_abstract: !firrtl.reset,
|
|
input clock : Clock ; CHECK: in %clock: !firrtl.clock,
|
|
output auto : UInt<1> ; CHECK: out %auto: !firrtl.uint<1>,
|
|
output auto11 : UInt<11> ; CHECK: out %auto11: !firrtl.uint<11>,
|
|
output sauto : SInt<9> ; CHECK: out %sauto: !firrtl.sint<9>,
|
|
input i8 : UInt<8> ; CHECK: in %i8: !firrtl.uint<8>,
|
|
input s1 : SInt<1> ; CHECK: in %s1: !firrtl.sint<1>,
|
|
input s8 : SInt<8> ; CHECK: in %s8: !firrtl.sint<8>,
|
|
input a1 : Analog<1> ; CHECK: in %a1: !firrtl.analog<1>,
|
|
input a8 : Analog<8> ; CHECK: in %a8: !firrtl.analog<8>,
|
|
input ab : {x : Analog<1>} ; CHECK: in %ab: !firrtl.bundle<x: analog<1>>)
|
|
|
|
; CHECK: %_t = firrtl.wire interesting_name : !firrtl.vector<uint<1>, 12>
|
|
wire _t : UInt<1>[12] @[Nodes.scala 370:76]
|
|
|
|
; CHECK: %_t_2 = firrtl.wire interesting_name : !firrtl.vector<uint<1>, 12>
|
|
wire _t_2 : UInt<1>[12]
|
|
|
|
; CHECK: firrtl.matchingconnect %_t, %_t_2 : !firrtl.vector<uint<1>, 12>
|
|
connect _t, _t_2
|
|
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue : !firrtl.uint<1>
|
|
; CHECK-NEXT: firrtl.matchingconnect %auto, [[INV]] : !firrtl.uint<1>
|
|
invalidate auto
|
|
|
|
; CHECK-NOT: firrtl.attach %a1
|
|
invalidate a1
|
|
|
|
; CHECK-NOT: firrtl.attach %ab
|
|
invalidate ab
|
|
|
|
; CHECK: firrtl.skip
|
|
skip @[SKipLoc.scala 42:24]
|
|
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue : !firrtl.uint<1>
|
|
; CHECK-NEXT: firrtl.matchingconnect %auto, [[INV]] : !firrtl.uint<1>
|
|
invalidate auto
|
|
|
|
; CHECK-NOT: firrtl.connect %reset
|
|
; CHECK-NOT: firrtl.matchingconnect %reset
|
|
invalidate reset
|
|
|
|
; CHECK: %out_0 = firrtl.wire interesting_name : !firrtl.bundle<member: bundle<"0": bundle<clock: clock, reset: uint<1>>>>
|
|
wire out_0 : { member : { 0 : { clock : Clock, reset : UInt<1>}}}
|
|
|
|
; CHECK: %_t_3 = firrtl.wire interesting_name : !firrtl.vector<uint<1>, 12>
|
|
; CHECK: [[A:%.+]] = firrtl.subindex %_t_3[0] : !firrtl.vector<uint<1>, 12>
|
|
; CHECK: %_t_4 = firrtl.wire interesting_name : !firrtl.vector<uint<1>, 12>
|
|
; CHECK: [[B:%.+]] = firrtl.subindex %_t_4[0] : !firrtl.vector<uint<1>, 12>
|
|
; CHECK: firrtl.matchingconnect [[A]], [[B]]
|
|
wire _t_3 : UInt<1>[12] @[Nodes.scala 370:76]
|
|
wire _t_4 : UInt<1>[12]
|
|
connect _t_3[0], _t_4[0] @[Xbar.scala 21:44]
|
|
|
|
; CHECK: %n1 = firrtl.node interesting_name %i8 : !firrtl.uint<8>
|
|
node n1 = i8
|
|
|
|
; CHECK: firrtl.add %reset, %reset : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<2>
|
|
node n2 = add(reset, reset)
|
|
|
|
; CHECK: firrtl.asClock %reset : (!firrtl.uint<1>) -> !firrtl.clock
|
|
node n3 = asClock(reset)
|
|
|
|
; CHECK: firrtl.asUInt %clock : (!firrtl.clock) -> !firrtl.uint<1>
|
|
node check_u0 = asUInt(clock)
|
|
; CHECK: firrtl.asUInt %i8 : (!firrtl.uint<8>) -> !firrtl.uint<8>
|
|
node check_u1 = asUInt(i8)
|
|
; CHECK: firrtl.asUInt %s8 : (!firrtl.sint<8>) -> !firrtl.uint<8>
|
|
node check_u2 = asUInt(s8)
|
|
; CHECK: firrtl.asUInt %a8 : (!firrtl.analog<8>) -> !firrtl.uint<8>
|
|
node check_u3 = asUInt(a8)
|
|
; CHECK: firrtl.asUInt %reset_abstract : (!firrtl.reset) -> !firrtl.uint<1>
|
|
node check_u5 = asUInt(reset_abstract)
|
|
; CHECK: firrtl.asUInt %reset_async : (!firrtl.asyncreset) -> !firrtl.uint<1>
|
|
node check_u6 = asUInt(reset_async)
|
|
|
|
; CHECK: firrtl.asSInt %clock : (!firrtl.clock) -> !firrtl.sint<1>
|
|
node check_s0 = asSInt(clock)
|
|
; CHECK: firrtl.asSInt %i8 : (!firrtl.uint<8>) -> !firrtl.sint<8>
|
|
node check_s1 = asSInt(i8)
|
|
; CHECK: firrtl.asSInt %s8 : (!firrtl.sint<8>) -> !firrtl.sint<8>
|
|
node check_s2 = asSInt(s8)
|
|
; CHECK: firrtl.asSInt %a8 : (!firrtl.analog<8>) -> !firrtl.sint<8>
|
|
node check_s3 = asSInt(a8)
|
|
; CHECK: firrtl.asSInt %reset_abstract : (!firrtl.reset) -> !firrtl.sint<1>
|
|
node check_s5 = asSInt(reset_abstract)
|
|
; CHECK: firrtl.asSInt %reset_async : (!firrtl.asyncreset) -> !firrtl.sint<1>
|
|
node check_s6 = asSInt(reset_async)
|
|
|
|
; CHECK: firrtl.asAsyncReset %clock : (!firrtl.clock) -> !firrtl.asyncreset
|
|
node check_ar0 = asAsyncReset(clock)
|
|
; CHECK: firrtl.asAsyncReset %reset : (!firrtl.uint<1>) -> !firrtl.asyncreset
|
|
node check_ar1 = asAsyncReset(reset)
|
|
; CHECK: firrtl.asAsyncReset %s1 : (!firrtl.sint<1>) -> !firrtl.asyncreset
|
|
node check_ar2 = asAsyncReset(s1)
|
|
; CHECK: firrtl.asAsyncReset %a1 : (!firrtl.analog<1>) -> !firrtl.asyncreset
|
|
node check_ar3 = asAsyncReset(a1)
|
|
; CHECK: firrtl.asAsyncReset %reset_abstract : (!firrtl.reset) -> !firrtl.asyncreset
|
|
node check_ar4 = asAsyncReset(reset_abstract)
|
|
; CHECK: firrtl.asAsyncReset %reset_async : (!firrtl.asyncreset) -> !firrtl.asyncreset
|
|
node check_ar5 = asAsyncReset(reset_async)
|
|
|
|
; CHECK: firrtl.asClock %clock : (!firrtl.clock) -> !firrtl.clock
|
|
node check_c0 = asClock(clock)
|
|
; CHECK: firrtl.asClock %reset : (!firrtl.uint<1>) -> !firrtl.clock
|
|
node check_c1 = asClock(reset)
|
|
; CHECK: firrtl.asClock %s1 : (!firrtl.sint<1>) -> !firrtl.clock
|
|
node check_c2 = asClock(s1)
|
|
; CHECK: firrtl.asClock %a1 : (!firrtl.analog<1>) -> !firrtl.clock
|
|
node check_c3 = asClock(a1)
|
|
; CHECK: firrtl.asClock %reset_abstract : (!firrtl.reset) -> !firrtl.clock
|
|
node check_c4 = asClock(reset_abstract)
|
|
; CHECK: firrtl.asClock %reset_async : (!firrtl.asyncreset) -> !firrtl.clock
|
|
node check_c5 = asClock(reset_async)
|
|
|
|
; CHECK: firrtl.node interesting_name %auto : !firrtl.uint<1>
|
|
node check_output = auto
|
|
|
|
; CHECK: %c42_ui10 = firrtl.constant 42 : !firrtl.const.uint<10>
|
|
; CHECK: %c171_ui8 = firrtl.constant 171 : !firrtl.const.uint<8>
|
|
; CHECK: firrtl.add %c42_ui10, %c171_ui8
|
|
; CHECK: firrtl.constCast
|
|
; CHECK: firrtl.matchingconnect %auto
|
|
connect auto11, add(UInt<10>(42), UInt<8>(0hAB))
|
|
|
|
; CHECK: %c-85_si8 = firrtl.constant -85 : !firrtl.const.sint<8>
|
|
connect sauto, add(s8, SInt<8>(-85))
|
|
|
|
; CHECK: firrtl.when %reset : !firrtl.uint<1> {
|
|
; CHECK: firrtl.matchingconnect %_t, %_t_2
|
|
; CHECK: } else {
|
|
; CHECK: firrtl.matchingconnect %_t, %_t_2
|
|
; CHECK: }
|
|
when reset : connect _t, _t_2 else : connect _t, _t_2
|
|
|
|
; CHECK: firrtl.when %reset : !firrtl.uint<1> {
|
|
; CHECK: [[N4A:%.+]] = firrtl.node interesting_name %_t_2
|
|
; CHECK: firrtl.matchingconnect %_t, [[N4A]]
|
|
; CHECK: } else {
|
|
; CHECK: [[N4B:%.+]] = firrtl.node interesting_name %_t_2
|
|
; CHECK: firrtl.matchingconnect %_t, [[N4B]]
|
|
; CHECK: }
|
|
when reset :
|
|
node n4 = _t_2
|
|
connect _t, n4
|
|
else :
|
|
node n4 = _t_2 ; 'n4' name is in unique scopes.
|
|
connect _t, n4
|
|
|
|
; CHECK: [[TMP:%.+]] = firrtl.constant 4
|
|
; CHECK: [[COND:%.+]] = firrtl.lt %reset, [[TMP]]
|
|
; CHECK: firrtl.when [[COND]] : !firrtl.uint<1> {
|
|
; CHECK: firrtl.matchingconnect %_t, %_t_2
|
|
; CHECK: }
|
|
; CHECK-NOT: else
|
|
when lt(reset, UInt(4)) : ;; When with no else.
|
|
connect _t, _t_2
|
|
|
|
; CHECK: firrtl.when %reset : !firrtl.uint<1> {
|
|
; CHECK: firrtl.matchingconnect %_t, %_t_2
|
|
; CHECK: } else {
|
|
; CHECK: [[COND:%.+]] = firrtl.not %reset
|
|
; CHECK: firrtl.when [[COND]] : !firrtl.uint<1> {
|
|
; CHECK: firrtl.matchingconnect %_t, %_t_2
|
|
; CHECK: }
|
|
; CHECK: }
|
|
when reset :
|
|
connect _t, _t_2
|
|
else when not(reset) :
|
|
connect _t, _t_2
|
|
|
|
; CHECK: firrtl.when %reset : !firrtl.uint<1> {
|
|
; CHECK: firrtl.matchingconnect %_t, %_t
|
|
; CHECK: } else {
|
|
; CHECK: [[COND:%.+]] = firrtl.not %reset
|
|
; CHECK: firrtl.when [[COND]] : !firrtl.uint<1> {
|
|
; CHECK: firrtl.matchingconnect %_t, %_t_2
|
|
; CHECK: } else {
|
|
; CHECK: firrtl.matchingconnect %_t, %_t_2
|
|
; CHECK: }
|
|
; CHECK: }
|
|
when reset:
|
|
connect _t, _t_2
|
|
else when not(reset) :
|
|
connect _t, _t_2
|
|
else :
|
|
connect _t, _t_2
|
|
|
|
; CHECK: firrtl.printf %clock, %reset, "Something interesting!\0A %x %x" (%_t, %_t_2) : !firrtl.clock, !firrtl.uint<1>, !firrtl.vector<uint<1>, 12>, !firrtl.vector<uint<1>, 12>
|
|
printf(clock, reset, "Something interesting!\n %x %x", _t, _t_2)
|
|
|
|
; CHECK: firrtl.printf %clock, %reset, "Something interesting!\0A %x %x" {name = "printf_0"} (%_t, %_t_2) : !firrtl.clock, !firrtl.uint<1>, !firrtl.vector<uint<1>, 12>, !firrtl.vector<uint<1>, 12>
|
|
printf(clock, reset, "Something interesting!\n %x %x", _t, _t_2) : printf_0
|
|
|
|
; CHECK: firrtl.stop %clock, %reset, 42 : !firrtl.clock, !firrtl.uint<1>
|
|
stop(clock, reset, 42)
|
|
|
|
; CHECK: firrtl.stop %clock, %reset, 42 {name = "stop_0"} : !firrtl.clock, !firrtl.uint<1>
|
|
stop(clock, reset, 42) : stop_0
|
|
|
|
; CHECK: firrtl.bits %i8 4 to 2 : (!firrtl.uint<8>) -> !firrtl.uint<3>
|
|
node n4 = bits(i8, 4, 2)
|
|
|
|
; CHECK: firrtl.shl %i8, 4 : (!firrtl.uint<8>) -> !firrtl.uint<12>
|
|
; CHECK: firrtl.shr %i8, 8 : (!firrtl.uint<8>) -> !firrtl.uint<0>
|
|
node n5 = or(shl(i8, 4), shr(i8, 8))
|
|
|
|
; CHECK: firrtl.dshl %i8, %{{.*}} : (!firrtl.uint<8>, !firrtl.const.uint<4>) -> !firrtl.uint<23>
|
|
node n6 = dshl(i8, UInt<4>(7))
|
|
; CHECK: firrtl.dshlw %i8, %{{.*}} : (!firrtl.uint<8>, !firrtl.const.uint<4>) -> !firrtl.uint<8>
|
|
node n6s = dshlw(i8, UInt<4>(7))
|
|
|
|
; CHECK: firrtl.cat %{{.*}}, %{{.*}} : (!firrtl.uint<12>, !firrtl.uint<23>) -> !firrtl.uint<35>
|
|
node n7 = cat(n5, n6)
|
|
|
|
; CHECK: firrtl.mux(%reset, %i8, %{{.*}}) : (!firrtl.uint<1>, !firrtl.uint<8>, !firrtl.const.uint) -> !firrtl.uint
|
|
node n8 = mux(reset, i8, UInt(4))
|
|
|
|
; CHECK: %_t_2621 = firrtl.regreset interesting_name %clock, %reset, %{{.*}} : !firrtl.clock, !firrtl.uint<1>, !firrtl.const.uint<4>, !firrtl.uint<4>
|
|
regreset _t_2621 : UInt<4>, clock, reset, UInt<4>(0h0) @[Edges.scala 230:27]
|
|
|
|
; CHECK: %_t_1601 = firrtl.regreset interesting_name %clock, %reset, %{{.*}} : !firrtl.clock, !firrtl.uint<1>, !firrtl.const.uint<2>, !firrtl.uint<2>
|
|
regreset _t_1601 : UInt<2>, clock, reset, UInt<2>(0h00) @[Edges.scala 230:27]
|
|
|
|
; CHECK: firrtl.div %i8, %{{.*}} : (!firrtl.uint<8>, !firrtl.const.uint<4>) -> !firrtl.uint<8>
|
|
node n9 = div(i8, UInt<4>(4))
|
|
|
|
; CHECK: firrtl.tail %i8, 7 : (!firrtl.uint<8>) -> !firrtl.uint<1>
|
|
; CHECK: firrtl.tail %i8, 0 : (!firrtl.uint<8>) -> !firrtl.uint<8>
|
|
; CHECK: firrtl.head %i8, 4 : (!firrtl.uint<8>) -> !firrtl.uint<4>
|
|
node n10 = add(add(tail(i8, 7), tail(i8, 0)), head(i8, 4))
|
|
|
|
; CHECK: firrtl.tail %{{.*}}, 3 : (!firrtl.sint<8>) -> !firrtl.uint<5>
|
|
node n10s = tail(asSInt(i8), 3)
|
|
|
|
; CHECK: %_t_2622 = firrtl.reg interesting_name %clock : !firrtl.clock, !firrtl.uint<4>
|
|
reg _t_2622 : UInt<4>, clock
|
|
|
|
; CHECK: %xyz_in = firrtl.instance xyz interesting_name @circuit(in in: !firrtl.uint<80>)
|
|
inst xyz of circuit
|
|
; CHECK: [[PAD:%.*]] = firrtl.pad %i8, 80 : (!firrtl.uint<8>) -> !firrtl.uint<80>
|
|
; CHECK: firrtl.matchingconnect %xyz_in, [[PAD]] : !firrtl.uint<80>
|
|
connect xyz.in, i8
|
|
|
|
; CHECK: %myext_in, %myext_out = firrtl.instance myext interesting_name @MyExtModule(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
|
inst myext of MyExtModule
|
|
connect myext.in, i8
|
|
printf(clock, reset, "Something interesting! %x", myext.out)
|
|
|
|
; CHECK: firrtl.when %reset : !firrtl.uint<1> {
|
|
when reset :
|
|
; CHECK: %reset_myext_in, %reset_myext_out = firrtl.instance reset_myext interesting_name @MyExtModule(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
|
inst reset_myext of MyExtModule
|
|
connect reset_myext.in, i8
|
|
; CHECK: }
|
|
|
|
; CHECK: firrtl.subaccess %_t[%i8] : !firrtl.vector<uint<1>, 12>, !firrtl.uint<8>
|
|
connect auto, _t[i8]
|
|
|
|
; CHECK: firrtl.subaccess %_t[%auto] : !firrtl.vector<uint<1>, 12>, !firrtl.uint<1>
|
|
connect auto, _t[auto]
|
|
|
|
; CHECK: %myMem = chirrtl.combmem interesting_name : !chirrtl.cmemory<bundle<id: uint<4>, resp: uint<2>>, 8>
|
|
cmem myMem : { id : UInt<4>, resp : UInt<2>} [8] @[Decoupled.scala 209:24]
|
|
|
|
; CHECK: %memValue_data, %memValue_port = chirrtl.memoryport Infer %myMem {name = "memValue"} : (!chirrtl.cmemory<bundle<id: uint<4>, resp: uint<2>>, 8>) -> (!firrtl.bundle<id: uint<4>, resp: uint<2>>, !chirrtl.cmemoryport)
|
|
; CHECK: chirrtl.memoryport.access %memValue_port[%i8], %clock : !chirrtl.cmemoryport, !firrtl.uint<8>, !firrtl.clock
|
|
infer mport memValue = myMem[i8], clock
|
|
connect auto11, memValue.id
|
|
|
|
; CHECK: %base_table_0 = chirrtl.seqmem interesting_name Undefined : !chirrtl.cmemory<vector<uint<1>, 9>, 256>
|
|
smem base_table_0 : UInt<1>[9] [256]
|
|
; CHECK: %base_table_1 = chirrtl.seqmem interesting_name Old : !chirrtl.cmemory<vector<uint<1>, 9>, 256>
|
|
smem base_table_1 : UInt<1>[9] [256], old
|
|
|
|
; CHECK: %tableValue_data, %tableValue_port = chirrtl.memoryport Read %base_table_1 {name = "tableValue"} : (!chirrtl.cmemory<vector<uint<1>, 9>, 256>) -> (!firrtl.vector<uint<1>, 9>, !chirrtl.cmemoryport)
|
|
; CHECK: chirrtl.memoryport.access %tableValue_port[%i8], %clock : !chirrtl.cmemoryport, !firrtl.uint<8>, !firrtl.clock
|
|
read mport tableValue = base_table_1[i8], clock
|
|
|
|
; Check that we can handle large memory sizes.
|
|
; CHECK: %testharness = chirrtl.seqmem interesting_name Undefined : !chirrtl.cmemory<vector<uint<8>, 16>, 2147483648>
|
|
smem testharness : UInt<8>[16][2147483648], undefined
|
|
|
|
; CHECK: firrtl.pad %i8, 10 : (!firrtl.uint<8>) -> !firrtl.uint<10>
|
|
node n11 = pad(i8, 10)
|
|
|
|
; CHECK: firrtl.andr %n11 : (!firrtl.uint<10>) -> !firrtl.uint<1>
|
|
node n12 = andr(n11)
|
|
|
|
; CHECK: = firrtl.not %auto : (!firrtl.uint<1>) -> !firrtl.uint<1>
|
|
node n13 = not(auto)
|
|
|
|
|
|
; CHECK: %_M__T_10, %_M__T_11, %_M__T_18 = firrtl.mem interesting_name Undefined {depth = 8 : i64, name = "_M", portNames = ["_T_10", "_T_11", "_T_18"]
|
|
; CHECK-SAME: readLatency = 0 : i32, writeLatency = 1 : i32} :
|
|
; CHECK-SAME: !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data: bundle<id: uint<4>>, mask: bundle<id: uint<1>>>,
|
|
; CHECK-SAME: !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data: bundle<id: uint<4>>, mask: bundle<id: uint<1>>>,
|
|
; CHECK-SAME: !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data flip: bundle<id: uint<4>>
|
|
mem _M : @[Decoupled.scala 209:24]
|
|
data-type => { id : UInt<4> }
|
|
depth => 8
|
|
read-latency => 0
|
|
write-latency => 1
|
|
reader => _T_18
|
|
writer => _T_10 _T_11
|
|
read-under-write => undefined
|
|
invalidate _M._T_18.addr @[Decoupled.scala 209:24]
|
|
invalidate _M._T_18.clk @[Decoupled.scala 209:24]
|
|
connect _M._T_18.en, UInt<1>(0h0) @[Decoupled.scala 209:24]
|
|
invalidate _M._T_10.addr @[Decoupled.scala 209:24]
|
|
invalidate _M._T_10.clk @[Decoupled.scala 209:24]
|
|
connect _M._T_10.en, UInt<1>(0h0) @[Decoupled.scala 209:24]
|
|
invalidate _M._T_10.data @[Decoupled.scala 209:24]
|
|
invalidate _M._T_10.mask @[Decoupled.scala 209:24]
|
|
|
|
; CHECK: firrtl.attach %a8, %a8, %a8 :
|
|
attach (a8, a8, a8)
|
|
|
|
wire pred: UInt <1>
|
|
wire en: UInt <1>
|
|
connect pred, eq(i8, i8)
|
|
connect en, not(reset)
|
|
; CHECK: firrtl.assert %clock, %pred, %en, "X equals Y when Z is valid" : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1> {eventControl = 0 : i32, isConcurrent = false}
|
|
assert(clock, pred, en, "X equals Y when Z is valid")
|
|
; CHECK: firrtl.assert %clock, %pred, %en, "X equals Y when Z is valid" : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1> {eventControl = 0 : i32, isConcurrent = false, name = "assert_0"}
|
|
assert(clock, pred, en, "X equals Y when Z is valid") : assert_0
|
|
; CHECK: firrtl.assert %clock, %pred, %en, "pred=%d, en=%d"(%pred, %en) : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1>, !firrtl.uint<1>, !firrtl.uint<1> {eventControl = 0 : i32, isConcurrent = false, name = "assert_1"}
|
|
assert(clock, pred, en, "pred=%d, en=%d", pred, en) : assert_1
|
|
; CHECK: firrtl.assume %clock, %pred, %en, "X equals Y when Z is valid" : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1> {eventControl = 0 : i32, isConcurrent = false}
|
|
assume(clock, pred, en, "X equals Y when Z is valid")
|
|
; CHECK: firrtl.assume %clock, %pred, %en, "X equals Y when Z is valid" : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1> {eventControl = 0 : i32, isConcurrent = false, name = "assume_0"}
|
|
assume(clock, pred, en, "X equals Y when Z is valid") : assume_0
|
|
; CHECK: firrtl.assume %clock, %pred, %en, "pred=%d, en=%d"(%pred, %en) : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1>, !firrtl.uint<1>, !firrtl.uint<1> {eventControl = 0 : i32, isConcurrent = false, name = "assume_1"}
|
|
assume(clock, pred, en, "pred=%d, en=%d", pred, en) : assume_1
|
|
; CHECK: firrtl.cover %clock, %pred, %en, "X equals Y when Z is valid" : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1> {eventControl = 0 : i32, isConcurrent = false}
|
|
cover(clock, pred, en, "X equals Y when Z is valid")
|
|
; CHECK: firrtl.cover %clock, %pred, %en, "X equals Y when Z is valid" : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1> {eventControl = 0 : i32, isConcurrent = false, name = "cover_0"}
|
|
cover(clock, pred, en, "X equals Y when Z is valid") : cover_0
|
|
|
|
; CHECK-LABEL: firrtl.module private @type_handling(
|
|
module type_handling :
|
|
wire _t_6 : { flip b : { bits : { source : UInt<7> } } }
|
|
node _t_8 = bits(_t_6.b.bits.source, 5, 0)
|
|
|
|
; CHECK: %flip1 = firrtl.wire interesting_name : !firrtl.bundle<x flip: bundle<a flip: uint>>
|
|
wire flip1 : { flip x : { flip a : UInt } }
|
|
; CHECK: %flip2 = firrtl.wire interesting_name : !firrtl.bundle<x flip: bundle<a flip: uint, b: analog>>
|
|
wire flip2 : { flip x : { flip a : UInt, b: Analog } }
|
|
; CHECK: %flip3 = firrtl.wire interesting_name : !firrtl.bundle<x flip: bundle<a flip: uint, b flip: analog>>
|
|
wire flip3 : { flip x : { flip a : UInt, flip b: Analog } }
|
|
; CHECK: %flip4 = firrtl.wire interesting_name : !firrtl.bundle<x flip: vector<bundle<a flip: uint>, 4>>
|
|
wire flip4 : { flip x : { flip a : UInt }[4] }
|
|
|
|
|
|
; CHECK-LABEL: firrtl.module private @expr_stmt_ambiguity(
|
|
module expr_stmt_ambiguity :
|
|
; CHECK: %reg = firrtl.wire interesting_name : !firrtl.uint
|
|
wire reg : UInt
|
|
; CHECK: firrtl.connect %reg,
|
|
connect reg, UInt(42)
|
|
|
|
; CHECK: %write = firrtl.wire
|
|
wire write : { id : UInt<4>, resp : UInt<2>}
|
|
|
|
; CHECK: firrtl.subfield %write[id]
|
|
connect write.id, UInt(1)
|
|
|
|
; CHECK-LABEL: firrtl.module private @expr_stmt_ambiguity2(
|
|
module expr_stmt_ambiguity2 :
|
|
; CHECK: firrtl.instance write interesting_name @circuit
|
|
inst write of circuit
|
|
; CHECK: firrtl.connect %write_in
|
|
connect write.in, UInt(1)
|
|
|
|
; CHECK-LABEL: firrtl.module private @oversize_shift(
|
|
module oversize_shift :
|
|
wire value : UInt<2>
|
|
; CHECK: firrtl.shr %value, 5 : (!firrtl.uint<2>) -> !firrtl.uint<0>
|
|
node n = shr(value, 5)
|
|
|
|
; CHECK-LABEL: firrtl.module private @when_else_ambiguity(
|
|
module when_else_ambiguity :
|
|
output out : UInt
|
|
input in : UInt
|
|
wire reset : UInt<1>
|
|
|
|
; CHECK: firrtl.when {{.*}} : !firrtl.uint<1> {
|
|
when reset : @[Debug.scala 1176:37]
|
|
; CHECK: firrtl.when {{.*}} : !firrtl.uint<1> {
|
|
when reset :
|
|
connect out, in
|
|
; CHECK: }
|
|
; CHECK: } else {
|
|
else :
|
|
; CHECK: firrtl.when {{.*}} : !firrtl.uint<1> {
|
|
when reset : @[Debug.scala 1180:39]
|
|
connect out, in
|
|
; CHECK: }
|
|
; CHECK: }
|
|
|
|
|
|
; CHECK-LABEL: firrtl.module private @chisel_when_mport_bug(
|
|
module chisel_when_mport_bug :
|
|
input cond : UInt<1>
|
|
input addr : UInt
|
|
input clock : Clock
|
|
|
|
; Memory ports should be declared in the scope of the cmemory, but should
|
|
; be enabled at the location of the mport.
|
|
|
|
; CHECK: %memory = chirrtl.seqmem interesting_name Undefined : !chirrtl.cmemory<vector<uint<1>, 9>, 256>
|
|
smem memory : UInt<1>[9] [256]
|
|
|
|
; CHECK: %xyz0_data, %xyz0_port = chirrtl.memoryport Read %memory {name = "xyz0"} : (!chirrtl.cmemory<vector<uint<1>, 9>, 256>) -> (!firrtl.vector<uint<1>, 9>, !chirrtl.cmemoryport)
|
|
; CHECK: firrtl.when %cond : !firrtl.uint<1> {
|
|
; CHECK: chirrtl.memoryport.access %xyz0_port[%addr], %clock : !chirrtl.cmemoryport, !firrtl.uint, !firrtl.clock
|
|
; CHECK: }
|
|
when cond :
|
|
read mport xyz0 = memory[addr], clock
|
|
|
|
; CHECK: firrtl.when %cond : !firrtl.uint<1> {
|
|
; CHECK: %n0 = firrtl.node interesting_name %xyz0_data : !firrtl.vector<uint<1>, 9>
|
|
; CHECK: }
|
|
when cond :
|
|
node n0 = xyz0
|
|
|
|
; CHECK: %n1 = firrtl.node interesting_name %xyz0_data : !firrtl.vector<uint<1>, 9>
|
|
node n1 = xyz0
|
|
|
|
|
|
; CHECK-LABEL: firrtl.module private @constant_implicit_cse(
|
|
module constant_implicit_cse :
|
|
input cond : UInt<1>
|
|
|
|
; CHECK: [[CST15:%.+]] = firrtl.constant 15 : !firrtl.const.uint<4>
|
|
; CHECK: %a = firrtl.node interesting_name [[CST15]]
|
|
node a = UInt<4>(15)
|
|
; CHECK: %b = firrtl.node interesting_name [[CST15]]
|
|
node b = UInt<4>(15)
|
|
|
|
;; Constants always get emitted to the top level.
|
|
; CHECK: [[CST7:%.+]] = firrtl.constant 7 : !firrtl.const.uint<4>
|
|
; CHECK: firrtl.when %cond : !firrtl.uint<1> {
|
|
when cond :
|
|
; CHECK: %c = firrtl.node interesting_name [[CST15]]
|
|
node c = UInt<4>(15)
|
|
; CHECK: %d = firrtl.node interesting_name [[CST7]]
|
|
node d = UInt<4>(7)
|
|
; CHECK: firrtl.when %cond : !firrtl.uint<1> {
|
|
when cond :
|
|
; CHECK: %e = firrtl.node interesting_name [[CST7]]
|
|
node e = UInt<4>(7)
|
|
; CHECK: }
|
|
; CHECK: }
|
|
|
|
; CHECK: %f = firrtl.node interesting_name [[CST15]]
|
|
node f = UInt<4>(15)
|
|
node g = UInt<4>(7)
|
|
|
|
; CHECK-LABEL: firrtl.module private @subfield_implicit_cse
|
|
module subfield_implicit_cse :
|
|
input i: {x: UInt<1>}
|
|
input cond: UInt<1>
|
|
output o: UInt<1>
|
|
|
|
; Subfields always get emitted by their declarations.
|
|
; CHECK: [[SUB:%.+]] = firrtl.subfield %i[x]
|
|
|
|
; CHECK: %n3 = firrtl.node interesting_name [[SUB]]
|
|
node n3 = i.x
|
|
|
|
; CHECK: firrtl.when %cond : !firrtl.uint<1> {
|
|
when cond:
|
|
; CHECK: %n4 = firrtl.node interesting_name [[SUB]]
|
|
node n4 = i.x
|
|
; CHECK: }
|
|
|
|
; Check that invalidation reuses subfields
|
|
wire w: {a: UInt<1>}[1]
|
|
; CHECK: %invalid = firrtl.invalidvalue : !firrtl.vector<bundle<a: uint<1>>, 1>
|
|
; CHECK: firrtl.matchingconnect %w, %invalid
|
|
invalidate w
|
|
; CHECK: %invalid_0 = firrtl.invalidvalue : !firrtl.vector<bundle<a: uint<1>>, 1>
|
|
; CHECK: firrtl.matchingconnect %w, %invalid_0
|
|
invalidate w
|
|
|
|
; CHECK-LABEL: firrtl.module private @flip_one
|
|
module flip_one :
|
|
input bf: { flip int_1 : UInt<1>, int_out : UInt<2>}
|
|
; CHECK: %0 = firrtl.subfield %bf[int_1]
|
|
; CHECK: %_T = firrtl.node interesting_name %0
|
|
node _T = bf.int_1
|
|
; CHECK: firrtl.when %_T : !firrtl.uint<1> {
|
|
when _T :
|
|
skip
|
|
|
|
; CHECK-LABEL: firrtl.module private @mem_depth_1
|
|
module mem_depth_1 :
|
|
input clock : Clock
|
|
input reset : UInt<1>
|
|
|
|
mem bar : @[Decoupled.scala 218:16]
|
|
data-type => UInt<3>
|
|
depth => 1
|
|
read-latency => 0
|
|
write-latency => 1
|
|
reader => io_deq_bits_MPORT
|
|
writer => MPORT
|
|
read-under-write => undefined
|
|
; CHECK: %bar_MPORT, %bar_io_deq_bits_MPORT = firrtl.mem interesting_name Undefined {depth = 1 : i64, name = "bar", portNames = ["MPORT", "io_deq_bits_MPORT"], readLatency = 0 : i32, writeLatency = 1 : i32} :
|
|
; CHECK: !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data: uint<3>, mask: uint<1>>,
|
|
; CHECK: !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data flip: uint<3>>
|
|
|
|
; CHECK-LABEL: firrtl.module private @mem_no_ports() {
|
|
; CHECK-NEXT: }
|
|
; https://github.com/llvm/circt/issues/531
|
|
module mem_no_ports :
|
|
mem bar : @[Decoupled.scala 218:16]
|
|
data-type => UInt<3>
|
|
depth => 1
|
|
read-latency => 0
|
|
write-latency => 1
|
|
read-under-write => undefined
|
|
|
|
; CHECK-LABEL: firrtl.module private @issue354(out %tmp5: !firrtl.sint<19>) {
|
|
module issue354 :
|
|
output tmp5: SInt<19>
|
|
connect tmp5, SInt<19>(8)
|
|
; CHECK: %c8_si19 = firrtl.constant 8 : !firrtl.const.sint<19>
|
|
; CHECK: [[VAL:%.*]] = firrtl.constCast %c8_si19 : (!firrtl.const.sint<19>) -> !firrtl.sint<19>
|
|
; CHECK: firrtl.matchingconnect %tmp5, [[VAL]] : !firrtl.sint<19>
|
|
|
|
; CHECK-LABEL: firrtl.module private @issue347
|
|
module issue347 :
|
|
output tmp12: SInt<4>
|
|
connect tmp12, SInt<4>(-4)
|
|
; CHECK: %c-4_si4 = firrtl.constant -4 : !firrtl.const.sint<4>
|
|
|
|
; CHECK-LABEL: firrtl.extmodule private @issue183<A: si32 = -1>()
|
|
extmodule issue183:
|
|
parameter A = -1
|
|
|
|
; The Scala FIRRTL Compiler allows this for an aggregate node with an internal
|
|
; analog.
|
|
; CHECK-LABEL: firrtl.module private @analog_in_aggregate_node
|
|
module analog_in_aggregate_node:
|
|
input a: { a: UInt<1>, b: Analog<1>}
|
|
; CHECK: %b = firrtl.node interesting_name %a : !firrtl.bundle<a: uint<1>, b: analog<1>>
|
|
node b = a
|
|
|
|
; Check that a register clock sink is converted to passive
|
|
; CHECK-LABEL: firrtl.module private @register_clock_passive
|
|
module register_clock_passive:
|
|
input clkIn: Clock
|
|
output clkOut: Clock
|
|
connect clkOut, clkIn
|
|
; CHECK: firrtl.reg interesting_name %clkOut
|
|
reg r: UInt<1>, clkOut
|
|
|
|
; Check that a register reset sink is converted to passive
|
|
; CHECK-LABEL: firrtl.module private @register_reset_passive
|
|
module register_reset_passive:
|
|
input clk: Clock
|
|
output rst: UInt<1>
|
|
invalidate rst
|
|
; CHECK: firrtl.regreset interesting_name %clk, %rst
|
|
regreset r: UInt<1>, clk, rst, UInt<1>(0)
|
|
|
|
; Check that a register init sink is converted to passive
|
|
; CHECK-LABEL: firrtl.module private @register_init_passive
|
|
module register_init_passive:
|
|
input clk: Clock
|
|
input rst: UInt<1>
|
|
output init: UInt<1>
|
|
invalidate init
|
|
; CHECK: firrtl.regreset interesting_name %clk, %rst, %init
|
|
regreset r: UInt<1>, clk, rst, init
|
|
|
|
; https://github.com/llvm/circt/issues/492
|
|
; CHECK-LABEL: firrtl.module private @WriteOnlyMemIssue492
|
|
module WriteOnlyMemIssue492 :
|
|
input clock: Clock
|
|
input wAddr: UInt<4>
|
|
input wEn: UInt<1>
|
|
input wMask: UInt<1>
|
|
input wData: UInt<8>
|
|
|
|
mem memory:
|
|
data-type => UInt<8>
|
|
depth => 16
|
|
writer => w
|
|
read-latency => 0
|
|
write-latency => 1
|
|
read-under-write => undefined
|
|
|
|
connect memory.w.clk, clock
|
|
connect memory.w.en, wEn
|
|
connect memory.w.addr, wAddr
|
|
connect memory.w.mask, wMask
|
|
connect memory.w.data, wData
|
|
|
|
; https://github.com/llvm/circt/issues/559
|
|
; CHECK-LABEL: firrtl.module private @TrickyIssue559
|
|
module TrickyIssue559:
|
|
input input: UInt<1>
|
|
output output: UInt<1>
|
|
; CHECK: firrtl.matchingconnect %output, %input
|
|
connect output, input
|
|
|
|
; CHECK-LABEL: firrtl.module private @CheckInvalids
|
|
module CheckInvalids_in0 :
|
|
input in0 : UInt<1>
|
|
; CHECK-NOT: firrtl.connect %in0
|
|
; CHECK-NOT: firrtl.matchingconnect %in0
|
|
invalidate in0
|
|
|
|
module CheckInvalids_in1 :
|
|
input in1 : { a : UInt<1>, b : UInt<1> }
|
|
; CHECK-NOT: firrtl.connect %in1
|
|
; CHECK-NOT: firrtl.matchingconnect %in1
|
|
invalidate in1
|
|
|
|
module CheckInvalids_in2 :
|
|
input in2 : { a : UInt<1>, flip b : UInt<1>}
|
|
; CHECK: [[IN2_B:%.+]] = firrtl.subfield %in2[b]
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue
|
|
; CHECK: firrtl.matchingconnect [[IN2_B]], [[INV]]
|
|
invalidate in2
|
|
|
|
module CheckInvalids_in3 :
|
|
input in3 : {a : { b : UInt<1>, flip c : UInt<1>}}
|
|
; CHECK: [[IN3_A:%.+]] = firrtl.subfield %in3[a]
|
|
; CHECK: [[IN3_A_C:%.+]] = firrtl.subfield [[IN3_A]][c]
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue
|
|
; CHECK: firrtl.matchingconnect [[IN3_A_C]], [[INV]]
|
|
invalidate in3
|
|
|
|
module CheckInvalids_out0 :
|
|
output out0 : UInt<1>
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue
|
|
; CHECK: firrtl.matchingconnect %out0, [[INV]]
|
|
invalidate out0
|
|
|
|
module CheckInvalids_out1 :
|
|
output out1 : { a : UInt<1>, b : UInt<1> }
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue : !firrtl.bundle<a: uint<1>, b: uint<1>>
|
|
; CHECK: firrtl.matchingconnect %out1, [[INV]]
|
|
invalidate out1
|
|
|
|
module CheckInvalids_out2 :
|
|
output out2 : { a : UInt<1>, flip b : UInt<1>}
|
|
; CHECK: [[OUT2_A:%.+]] = firrtl.subfield %out2[a]
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue
|
|
; CHECK: firrtl.matchingconnect [[OUT2_A]], [[INV]]
|
|
invalidate out2
|
|
|
|
module CheckInvalids_out3 :
|
|
output out3 : {a : { b : UInt<1>, flip c : UInt<1>}}
|
|
; CHECK: [[OUT3_A:%.+]] = firrtl.subfield %out3[a]
|
|
; CHECK: [[OUT3_A_B:%.+]] = firrtl.subfield [[OUT3_A]][b]
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue
|
|
; CHECK: firrtl.matchingconnect [[OUT3_A_B]], [[INV]]
|
|
invalidate out3
|
|
|
|
module CheckInvalids_wires :
|
|
; CHECK: %wire0 = firrtl.wire
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue
|
|
; CHECK: firrtl.matchingconnect %wire0, [[INV]]
|
|
wire wire0 : UInt<1>
|
|
invalidate wire0
|
|
|
|
; CHECK: %wire1 = firrtl.wire
|
|
; CHECK: [[WIRE1_B:%.+]] = firrtl.subfield %wire1[b]
|
|
; CHECK: [[WIRE1_A:%.+]] = firrtl.subfield %wire1[a]
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue
|
|
; CHECK: firrtl.matchingconnect [[WIRE1_A]], [[INV]]
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue
|
|
; CHECK: firrtl.matchingconnect [[WIRE1_B]], [[INV]]
|
|
wire wire1 : {a : UInt<1>, flip b : UInt<1> }
|
|
invalidate wire1
|
|
|
|
; An analog in the leaf of a wire should be attached not connected.
|
|
; CHECK: %wire2 = firrtl.wire
|
|
; CHECK: [[WIRE2_X:%.+]] = firrtl.subfield %wire2[x]
|
|
; CHECK: [[WIRE2_X_B:%.+]] = firrtl.subfield [[WIRE2_X]][b]
|
|
; CHECK: [[WIRE2_X_A:%.+]] = firrtl.subfield [[WIRE2_X]][a]
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue
|
|
; CHECK: firrtl.matchingconnect [[WIRE2_X_A]], [[INV]]
|
|
; CHECK-NOT: firrtl.attach [[WIRE2_X_B]], [[INV]]
|
|
wire wire2 : {x : {flip a : UInt<1>, flip b: Analog<1> } }
|
|
invalidate wire2
|
|
|
|
; https://github.com/llvm/circt/issues/563
|
|
; CHECK: %U0_in0, %U0_in1, %U0_out0, %U0_out1 = firrtl.instance U0 interesting_name @mod_0_563
|
|
inst U0 of mod_0_563
|
|
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue
|
|
; CHECK: firrtl.matchingconnect %U0_in0, [[INV]]
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue : !firrtl.bundle<a: uint<5>>
|
|
; CHECK: firrtl.matchingconnect %U0_in1, [[INV]]
|
|
invalidate U0
|
|
|
|
; This reference is declared after its first use.
|
|
; https://github.com/llvm/circt/issues/163
|
|
module mod_0_563 :
|
|
input in0: UInt<5>
|
|
input in1: { a : UInt<5> }
|
|
output out0: UInt<5>
|
|
output out1: { a : UInt<5> }
|
|
connect out0, in0
|
|
connect out1, in1
|
|
|
|
; https://github.com/llvm/circt/issues/606
|
|
; CHECK-LABEL: firrtl.module private @mutableSubIndex606
|
|
module mutableSubIndex606 :
|
|
output io : UInt<1>[8]
|
|
; CHECK: %0 = firrtl.subindex %io[0] : !firrtl.vector<uint<1>, 8>
|
|
; CHECK: [[VAL:%.*]] = firrtl.constCast %c0_ui1 : (!firrtl.const.uint<1>) -> !firrtl.uint<1>
|
|
; CHECK: firrtl.matchingconnect %0, [[VAL]] : !firrtl.uint<1>
|
|
connect io[0], UInt<1>(0h00)
|
|
|
|
|
|
; https://github.com/llvm/circt/issues/782
|
|
; CHECK-LABEL: mem_madness782
|
|
module mem_madness782:
|
|
input clock: Clock
|
|
input rAddr: UInt<4>
|
|
input rEn: UInt<1>
|
|
output rData: UInt<8>
|
|
|
|
; CHECK: %mem_r = firrtl.mem interesting_name Undefined {depth = 16 : i64, name = "mem", portNames = ["r"], readLatency = 2 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: uint<8>>
|
|
mem mem:
|
|
data-type => UInt<8>
|
|
depth => 16
|
|
reader => r
|
|
read-latency => 2
|
|
write-latency => 1
|
|
read-under-write => undefined
|
|
|
|
connect mem.r.clk, clock
|
|
connect mem.r.en, rEn
|
|
connect mem.r.addr, rAddr
|
|
connect rData, mem.r.data
|
|
|
|
; Test that behavioral memory reads and writes both work and that flow checks
|
|
; don't fail here. (A memory port should have duplex flow.)
|
|
; See: https://github.com/llvm/circt/issues/1058
|
|
; CHECK-LABEL: firrtl.module private @BehavioralMemory
|
|
module BehavioralMemory:
|
|
input clock: Clock
|
|
input rAddr: UInt<3>
|
|
output rData: UInt<1>
|
|
input wAddr: UInt<3>
|
|
input wData: UInt<1>
|
|
|
|
cmem a: UInt<1>[8]
|
|
|
|
; CHECK: firrtl.matchingconnect %rData, %r
|
|
infer mport r = a[rAddr], clock
|
|
connect rData, r
|
|
|
|
; CHECK: firrtl.matchingconnect %w_data, %wData
|
|
infer mport w = a[wAddr], clock
|
|
connect w, wData
|
|
|
|
; Test that a mux with an unknown width select line parses. This is a check
|
|
; of the predicate enforced on UInt1Type.
|
|
; CHECK-LABEL: firrtl.module private @MuxUnknownWidthSelect_Issue1108
|
|
module MuxUnknownWidthSelect_Issue1108:
|
|
input a: UInt<1>
|
|
input b: UInt<1>
|
|
input sel: UInt
|
|
output c: UInt<8>
|
|
connect c, mux(sel, a, b)
|
|
|
|
; Test that a mux with aggregate type is still compatible even if the leaf
|
|
; types disagree in their width.
|
|
; CHECK-LABEL: firrtl.module private @MuxAggregateWidthMismatch_Issue2806
|
|
module MuxAggregateWidthMismatch_Issue2806:
|
|
input a: UInt<1>[1]
|
|
input b: UInt<32>[1]
|
|
input x: {u: UInt<1>, v: UInt<2>}
|
|
input y: {u: UInt<32>, v: UInt<2>}
|
|
input sel: UInt<1>
|
|
output c: UInt[1]
|
|
output z: {u: UInt, v: UInt}
|
|
; CHECK: firrtl.mux(%sel, %a, %b)
|
|
; CHECK-SAME: -> !firrtl.vector<uint<32>, 1>
|
|
; CHECK: firrtl.mux(%sel, %x, %y)
|
|
; CHECK-SAME: -> !firrtl.bundle<u: uint<32>, v: uint<2>>
|
|
connect c, mux(sel, a, b)
|
|
connect z, mux(sel, x, y)
|
|
|
|
; CHECK-LABEL: firrtl.extmodule private @VerbatimStringParam
|
|
; CHECK-SAME: <TYPE: none = #hw.param.verbatim<"bit">,
|
|
; CHECK-SAME: FORMAT: none = #hw.param.verbatim<"xyz_timeout=%d\\n">,
|
|
; CHECK-SAME: MIXED_QUOTES: none = #hw.param.verbatim<"\22'\\\22">>
|
|
extmodule VerbatimStringParam :
|
|
parameter TYPE = 'bit'
|
|
parameter FORMAT = 'xyz_timeout=%d\n'
|
|
parameter MIXED_QUOTES = '"\'\"'
|
|
; "
|
|
|
|
; CHECK-LABEL: firrtl.module private @issue1303
|
|
module issue1303:
|
|
output out: Reset
|
|
connect out, UInt(1)
|
|
; CHECK: %[[c1:.*]] = firrtl.constant 1 : !firrtl.const.uint
|
|
; CHECK-NEXT: %[[c2:.*]] = firrtl.resetCast %[[c1]]
|
|
; CHECK-NEXT: %[[c3:.*]] = firrtl.constCast %[[c2]]
|
|
; CHECK-NEXT: firrtl.matchingconnect %out, %[[c3]] : !firrtl.reset
|
|
|
|
|
|
; CHECK-LABEL: @resetBundle
|
|
module resetBundle:
|
|
input a: {a: UInt<1>, b: AsyncReset}
|
|
output b: {a: Reset, b: Reset}
|
|
|
|
connect b, a
|
|
; CHECK: %1 = firrtl.subfield %a[a] : !firrtl.bundle<a: uint<1>, b: asyncreset>
|
|
; CHECK: %[[r1:.*]] = firrtl.resetCast %1
|
|
; CHECK: firrtl.matchingconnect %0, %[[r1]] : !firrtl.reset
|
|
; CHECK: %3 = firrtl.subfield %b[b] : !firrtl.bundle<a: reset, b: reset>
|
|
; CHECK: %4 = firrtl.subfield %a[b] : !firrtl.bundle<a: uint<1>, b: asyncreset>
|
|
; CHECK: %[[r4:.*]] = firrtl.resetCast %4
|
|
; CHECK: firrtl.matchingconnect %3, %[[r4]] : !firrtl.reset
|
|
|
|
module LargeMem :
|
|
input clock : Clock
|
|
input reset : Reset
|
|
; CHECK: !chirrtl.cmemory<vector<uint<8>, 16>, 34359738368>
|
|
smem testharness : UInt<8>[16] [34359738368]
|
|
node w_addr = UInt<36>(42) @[Cat.scala 31:58]
|
|
write mport MPORT = testharness[w_addr], clock
|
|
|
|
; Module as identifier
|
|
; Test parsing of "module" as an identifier for instance and module names
|
|
extmodule SomeModule:
|
|
input in: UInt<8>
|
|
|
|
module ModuleAsIdentifier:
|
|
inst module of SomeModule
|
|
; CHECK: firrtl.instance module interesting_name @SomeModule
|
|
connect module.in, UInt(1)
|
|
|
|
; CHECK-LABEL: firrtl.module private @EnumTypes
|
|
module EnumTypes:
|
|
; CHECK-SAME: in %i: !firrtl.enum<Some: uint<8>, None: uint<0>>
|
|
input i : {| Some : UInt<8>, None |}
|
|
output o : UInt<8>
|
|
|
|
; CHECK: %c0_ui8 = firrtl.constant 0 : !firrtl.const.uint<8>
|
|
; CHECK: %0 = firrtl.enumcreate Some(%c0_ui8) : (!firrtl.const.uint<8>) -> !firrtl.enum<Some: uint<8>, None: uint<0>>
|
|
; CHECK: %some = firrtl.node interesting_name %0 : !firrtl.enum<Some: uint<8>, None: uint<0>>
|
|
node some = {|Some : UInt<8>, None|}(Some, UInt<8>(0))
|
|
; CHECK: %c0_ui0 = firrtl.constant 0 : !firrtl.const.uint<0>
|
|
; CHECK: %1 = firrtl.enumcreate None(%c0_ui0) : (!firrtl.const.uint<0>) -> !firrtl.enum<Some: uint<8>, None: uint<0>>
|
|
; CHECK: %none = firrtl.node {{.*}} %1 : !firrtl.enum<Some: uint<8>, None: uint<0>>
|
|
node none = {|Some : UInt<8>, None|}(None)
|
|
|
|
; CHECK: firrtl.match %i : !firrtl.enum<Some: uint<8>, None: uint<0>> {
|
|
match i:
|
|
; CHECK: case Some(%arg0) {
|
|
; CHECK: firrtl.matchingconnect %o, %arg0 : !firrtl.uint<8>
|
|
; CHECK: }
|
|
Some(x):
|
|
connect o, x
|
|
; CHECK: case None(%arg0) {
|
|
; CHECK: %invalid_ui8 = firrtl.invalidvalue : !firrtl.uint<8>
|
|
; CHECK: firrtl.matchingconnect %o, %invalid_ui8 : !firrtl.uint<8>
|
|
; CHECK: }
|
|
None:
|
|
invalidate o
|
|
|
|
; CHECK-LABEL: firrtl.module private @EnumInfer(
|
|
module EnumInfer:
|
|
input i : {| A: UInt<8>, None |}
|
|
output o : {| A: UInt, None |}
|
|
|
|
; CHECK: connect %o, %i
|
|
connect o, i
|
|
|
|
; CHECK-LABEL: module private @RefsChild(
|
|
; CHECK-SAME: out %r: !firrtl.probe<uint<1>>
|
|
; CHECK-SAME: out %rw: !firrtl.rwprobe<uint<1>>
|
|
module RefsChild :
|
|
input in : UInt<1>
|
|
output r : Probe<UInt<1>>
|
|
output rw : RWProbe<UInt<1>>
|
|
|
|
; CHECK-NEXT: %[[NODE:.+]] = firrtl.node sym @[[NODE_RW_SYM:[^ ]+]]
|
|
node n = in
|
|
; CHECK-NEXT: %[[REF:.+]] = firrtl.ref.send %[[NODE]]
|
|
; CHECK-NEXT: ref.define %r, %[[REF]]
|
|
define r = probe(n)
|
|
; CHECK: %[[NODE_RWREF:.+]] = firrtl.ref.rwprobe <@RefsChild::@[[NODE_RW_SYM]]>
|
|
; CHECK-NEXT: ref.define %rw, %[[NODE_RWREF]]
|
|
define rw = rwprobe(n)
|
|
|
|
; CHECK-LABEL: module private @RefsChildOpenAgg(
|
|
; CHECK-SAME: in %in: !firrtl.openbundle<a: uint<1>, rw flip: rwprobe<uint<1>>> sym [<@[[SYM:[^,]+]],1,
|
|
module RefsChildOpenAgg :
|
|
input in : { a : UInt<1>, flip rw: RWProbe<UInt<1>> }
|
|
; CHECK-NEXT: %[[IN_RW:[^ ]+]] = firrtl.opensubfield %in[rw]
|
|
; CHECK-NEXT: %[[RWPROBE_IN_A:[^ ]+]] = firrtl.ref.rwprobe <@RefsChildOpenAgg::@[[SYM]]>
|
|
; CHECK-NEXT: firrtl.ref.define %[[IN_RW]], %[[RWPROBE_IN_A]]
|
|
define in.rw = rwprobe(in.a)
|
|
|
|
; CHECK-LABEL: module private @Refs(
|
|
module Refs :
|
|
input in : const UInt<1>
|
|
output r : Probe<const UInt>
|
|
output rw : RWProbe<UInt>
|
|
output notrw : Probe<UInt>
|
|
output out : UInt<1>
|
|
output out2 : UInt<1>
|
|
output outconst : const UInt<1>
|
|
; CHECK-SAME: out %agg_out: !firrtl.probe<bundle<a: uint<1>, b: const.uint>>
|
|
output agg_out : Probe<{a: UInt<1>, b: const UInt}>
|
|
output field_rw : RWProbe<UInt<1>>
|
|
|
|
; CHECK-NEXT: %[[RC_IN:.+]], %[[RC_R:.+]], %[[RC_RW:.+]] = firrtl.instance rc
|
|
inst rc of RefsChild
|
|
connect rc.in, in
|
|
; CHECK: %[[OUTREF:.+]] = firrtl.ref.send %outconst
|
|
; CHECK-NEXT: %[[OUTREF_CAST:.+]] = firrtl.ref.cast %[[OUTREF]] : (!firrtl.probe<const.uint<1>>) -> !firrtl.probe<const.uint>
|
|
; CHECK-NEXT: ref.define %r, %[[OUTREF_CAST]]
|
|
define r = probe(outconst)
|
|
; CHECK-NEXT: %[[RC_RW_CAST:.+]] = firrtl.ref.cast %[[RC_RW]] : (!firrtl.rwprobe<uint<1>>) -> !firrtl.rwprobe<uint>
|
|
; CHECK-NEXT: ref.define %rw, %[[RC_RW_CAST]]
|
|
; CHECK-SAME: rwprobe<uint>
|
|
define rw = rc.rw
|
|
|
|
; CHECK-NEXT: %[[RC_RW_CAST_PROBE:.+]] = firrtl.ref.cast %[[RC_RW]] : (!firrtl.rwprobe<uint<1>>) -> !firrtl.probe<uint>
|
|
; CHECK-NEXT: ref.define %notrw, %[[RC_RW_CAST_PROBE]]
|
|
; CHECK-SAME: firrtl.probe
|
|
define notrw = rc.rw
|
|
|
|
; CHECK-NEXT: %[[READ_RC_R:.+]] = firrtl.ref.resolve %[[RC_R]]
|
|
; CHECK-NEXT: connect %out, %[[READ_RC_R]]
|
|
connect out, read(rc.r)
|
|
; CHECK-NEXT: %[[READ_RC_RW:.+]] = firrtl.ref.resolve %[[RC_RW]]
|
|
; CHECK-NEXT: connect %out, %[[READ_RC_RW]]
|
|
connect out, read(rc.rw)
|
|
|
|
; ref.sub parsing
|
|
; CHECK-DAG: %[[AGG:.+]] = firrtl.wire interesting_name : !firrtl.bundle<a flip: const.uint<1>, b: uint>
|
|
; CHECK-DAG: %[[AGG2:.+]] = firrtl.wire interesting_name : !firrtl.bundle<a: uint, b flip: uint<1>>
|
|
wire agg : { flip a : const UInt<1>, b : UInt }
|
|
wire agg2 : { a : UInt, flip b : UInt<1> }
|
|
; CHECK-DAG: %[[AGG_B:.+]] = firrtl.subfield %[[AGG]][b]
|
|
; CHECK-DAG: %[[AGG_B_PROBE:.+]] = firrtl.ref.send %[[AGG_B]]
|
|
; CHECK-DAG: %[[READ_AGG_B_PROBE:.+]] = firrtl.ref.resolve %[[AGG_B_PROBE]]
|
|
; CHECK-DAG: connect %out2, %[[READ_AGG_B_PROBE]]
|
|
connect out2, read(probe(agg.b))
|
|
; CHECK-DAG: %[[AGG2_PROBE:.+]] = firrtl.ref.send %[[AGG2]]
|
|
; CHECK-DAG: %[[READ_AGG2_PROBE:.+]] = firrtl.ref.resolve %[[AGG2_PROBE]]
|
|
; CHECK-DAG: %[[READ_AGG2_PROBE__B:.+]] = firrtl.subfield %[[READ_AGG2_PROBE]][b]
|
|
; CHECK-DAG: connect %out2, %[[READ_AGG2_PROBE__B]]
|
|
connect out2, read(probe(agg2)).b
|
|
|
|
; CHECK: %[[AGG3:.+]] = firrtl.wire
|
|
wire agg3 : const { a : UInt<1>, b : UInt }
|
|
; CHECK-NEXT: %[[AGG3_PROBE:.+]] = firrtl.ref.send %[[AGG3]]
|
|
; CHECK-NEXT: %[[AGG3_PROBE_CAST:.+]] = firrtl.ref.cast %[[AGG3_PROBE]] : (!firrtl.probe<const.bundle<a: uint<1>, b: uint>>) -> !firrtl.probe<bundle<a: uint<1>, b: const.uint>>
|
|
; CHECK-NEXT: ref.define %agg_out, %[[AGG3_PROBE_CAST]]
|
|
define agg_out = probe(agg3)
|
|
|
|
; CHECK: %[[PROBE_IN:.+]] = firrtl.ref.send %in
|
|
; CHECK-DAG: %[[READ_PROBE_IN:.+]] = firrtl.ref.resolve %[[PROBE_IN]]
|
|
; CHECK-DAG: %[[SUM:.+]] = firrtl.and %[[READ_PROBE_IN]],
|
|
connect outconst, and(read(probe(in)), UInt(1))
|
|
|
|
; CHECK: %[[AGG4:.+]] = firrtl.wire sym [<@[[AGG4_0_b_x_SYM:[^ ]+]],4,public>]
|
|
wire agg4 : { a : UInt, flip b : {x : UInt<1>} }[2]
|
|
; (static ref expr creates dead subfield accesses, skip)
|
|
; CHECK: %[[AGG4_RW_0_b_x:.+]] = firrtl.ref.rwprobe <@Refs::@[[AGG4_0_b_x_SYM]]>
|
|
; CHECK-NEXT: firrtl.ref.define %field_rw, %[[AGG4_RW_0_b_x]]
|
|
define field_rw = rwprobe(agg4[0].b.x)
|
|
|
|
; CHECK: %inst_rw = firrtl.wire : !firrtl.rwprobe<uint<1>>
|
|
; CHECK-NEXT: %inst_rw2 = firrtl.wire : !firrtl.rwprobe<uint<1>>
|
|
; CHECK-NEXT: %rc2_in_bounce = firrtl.wire sym @[[RC2_IN_BOUNCE_SYM:[^ ]+]]
|
|
; CHECK-NEXT: %rc2_in, %rc2_r, %rc2_rw = firrtl.instance rc2
|
|
; CHECK-NEXT: firrtl.matchingconnect %rc2_in, %rc2_in_bounce
|
|
wire inst_rw : RWProbe<UInt<1>>
|
|
wire inst_rw2 : RWProbe<UInt<1>>
|
|
inst rc2 of RefsChild
|
|
|
|
; CHECK: %[[IN_CAST:[^ ]+]] = firrtl.constCast %in :
|
|
; CHECK: firrtl.matchingconnect %rc2_in_bounce, %[[IN_CAST]]
|
|
connect rc2.in, in
|
|
; CHECK-NEXT: firrtl.when %rc2_in_bounce :
|
|
; CHECK-NEXT: %[[RWPROBE_RC2_IN_BOUNCE_1:[^ ]+]] = firrtl.ref.rwprobe <@Refs::@[[RC2_IN_BOUNCE_SYM]]>
|
|
; CHECK-NEXT: firrtl.ref.define %inst_rw, %[[RWPROBE_RC2_IN_BOUNCE_1]]
|
|
; CHECK-NEXT: }
|
|
when rc2.in:
|
|
define inst_rw = rwprobe(rc2.in)
|
|
; CHECK-NEXT: firrtl.matchingconnect %rc2_in_bounce,
|
|
connect rc2.in, rc.in
|
|
; CHECK-NEXT: %[[RWPROBE_RC2_IN_BOUNCE_2:[^ ]+]] = firrtl.ref.rwprobe <@Refs::@[[RC2_IN_BOUNCE_SYM]]>
|
|
; CHECK-NEXT: firrtl.ref.define %inst_rw2, %[[RWPROBE_RC2_IN_BOUNCE_2]]
|
|
define inst_rw2 = rwprobe(rc2.in)
|
|
|
|
; CHECK-LABEL: module private @ForceRelease(
|
|
module ForceRelease :
|
|
input in : UInt<1>
|
|
input clock : Clock
|
|
input cond : UInt<1>
|
|
|
|
; CHECK-NEXT: %{{.+}}, %{{.+}}, %[[RC_RW:.+]] = firrtl.instance rc
|
|
inst rc of RefsChild
|
|
connect rc.in, in
|
|
|
|
; Check (const) literal works, even if uninferred width.
|
|
; Cast reference to more general form as needed.
|
|
; CHECK: %[[RC_RW_CAST:.+]] = firrtl.ref.cast %[[RC_RW]] : (!firrtl.rwprobe<uint<1>>) -> !firrtl.rwprobe<uint>
|
|
; CHECK: firrtl.ref.force_initial %[[TRUE:.+]], %[[RC_RW_CAST]], %{{.+}} : !firrtl.uint<1>, !firrtl.rwprobe<uint>, !firrtl.const.uint
|
|
force_initial(rc.rw, UInt(0))
|
|
|
|
; CHECK: firrtl.ref.force %clock, %cond, %[[RC_RW]], %{{.+}} : !firrtl.clock, !firrtl.uint<1>, !firrtl.rwprobe<uint<1>>, !firrtl.const.uint<1>
|
|
force(clock, cond, rc.rw, UInt<1>(1))
|
|
; CHECK: %[[NOT_COND:.+]] = firrtl.not %cond
|
|
; CHECK: firrtl.ref.release %clock, %[[NOT_COND]], %[[RC_RW]] : !firrtl.clock, !firrtl.uint<1>, !firrtl.rwprobe<uint<1>>
|
|
release(clock, not(cond), rc.rw)
|
|
|
|
; CHECK-NEXT: %{{.+}}, %{{.+}}, %[[RC2_RW:.+]] = firrtl.instance rc2
|
|
inst rc2 of RefsChild
|
|
connect rc2.in, in
|
|
; CHECK: firrtl.ref.release_initial %[[TRUE]], %[[RC2_RW]] : !firrtl.uint<1>, !firrtl.rwprobe<uint<1>>
|
|
release_initial(rc2.rw)
|
|
|
|
; CHECK-LABEL: extmodule private @RefExtABI
|
|
; CHECK-NOT: internalPaths
|
|
extmodule RefExtABI :
|
|
input in : UInt<1>
|
|
output r : Probe<UInt<1>>
|
|
output data : UInt<3>
|
|
output r2 : Probe<{a : UInt<3>}[3]>
|
|
|
|
; CHECK-LABEL: @RWProbePort(
|
|
module RWProbePort:
|
|
; CHECK: in %in: !firrtl.vector<uint<1>, 2> sym [<@[[IN_SYM:.+]],2,public>],
|
|
input in : UInt<1>[2]
|
|
output p : RWProbe<UInt<1>>
|
|
; CHECK: firrtl.ref.rwprobe <@RWProbePort::@[[IN_SYM]]> : !firrtl.rwprobe<uint<1>>
|
|
define p = rwprobe(in[1])
|
|
|
|
; CHECK-LABEL: @RWProbeUninferredPort(
|
|
module RWProbeUninferredPort:
|
|
; CHECK: in %in: !firrtl.vector<uint, 2> sym [<@[[IN_SYM:.+]],2,public>],
|
|
input in : UInt[2]
|
|
output p : RWProbe<UInt>
|
|
; CHECK: firrtl.ref.rwprobe <@RWProbeUninferredPort::@[[IN_SYM]]> : !firrtl.rwprobe<uint>
|
|
define p = rwprobe(in[1])
|
|
|
|
; CHECK-LABEL: @RWProbeUninferredReset(
|
|
module RWProbeUninferredReset:
|
|
; CHECK: in %in: !firrtl.bundle<a: reset> sym [<@[[IN_SYM:.+]],1,public>],
|
|
input in : {a : Reset}
|
|
output p : RWProbe<Reset>
|
|
; CHECK: firrtl.ref.rwprobe <@RWProbeUninferredReset::@[[IN_SYM]]> : !firrtl.rwprobe<reset>
|
|
define p = rwprobe(in.a)
|
|
|
|
; CHECK-LABEL: module private @ProbeInvalidate
|
|
; CHECK-NEXT: }
|
|
module ProbeInvalidate:
|
|
output p : Probe<UInt<1>>
|
|
invalidate p
|
|
|
|
; CHECK-LABEL: module private @NumericFields
|
|
; See: https://github.com/llvm/circt/issues/5110
|
|
module NumericFields:
|
|
input a: {0: {0: {bar: UInt<1>}}}
|
|
output b: UInt<1>
|
|
input c: {0: {0: {0: {bar: UInt<1>}}}}
|
|
output d: UInt<1>
|
|
|
|
; CHECK: %0 = firrtl.subfield %c["0"]
|
|
; CHECK-NEXT: %1 = firrtl.subfield %0["0"]
|
|
; CHECK-NEXT: %2 = firrtl.subfield %1["0"]
|
|
; CHECK-NEXT: %3 = firrtl.subfield %2[bar]
|
|
; CHECK-NEXT: %4 = firrtl.subfield %a["0"]
|
|
; CHECK-NEXT: %5 = firrtl.subfield %4["0"]
|
|
; CHECK-NEXT: %6 = firrtl.subfield %5[bar]
|
|
connect b, a.0.0.bar
|
|
connect d, c.0.0.0.bar
|
|
; CHECK-NEXT: firrtl.matchingconnect %b, %6
|
|
; CHECK-NEXT: firrtl.matchingconnect %d, %3
|
|
|
|
; CHECK-LABEL: firrtl.module private @ConstTypes(
|
|
module ConstTypes:
|
|
input c: const Clock ; CHECK: %c: !firrtl.const.clock,
|
|
input r: const Reset ; CHECK: %r: !firrtl.const.reset,
|
|
input ar: const AsyncReset ; CHECK: %ar: !firrtl.const.asyncreset,
|
|
input a: const Analog ; CHECK: %a: !firrtl.const.analog,
|
|
input a8: const Analog<8> ; CHECK: %a8: !firrtl.const.analog<8>,
|
|
input s: const SInt ; CHECK: %s: !firrtl.const.sint,
|
|
input s4: const SInt<4> ; CHECK: %s4: !firrtl.const.sint<4>,
|
|
input u: const UInt ; CHECK: %u: !firrtl.const.uint,
|
|
|
|
; CHECK: %b: !firrtl.const.bundle<int_1 flip: uint<1>, int_out: uint<2>>
|
|
input b: const {flip int_1 : UInt<1>, int_out : UInt<2>}
|
|
; CHECK: %b_constfields: !firrtl.bundle<int_1 flip: const.uint<1>, int_out: const.uint<2>>
|
|
input b_constfields: {flip int_1 : const UInt<1>, int_out : const UInt<2>}
|
|
; CHECK: %mixedb: !firrtl.bundle<a: sint<1>, b: const.uint<2>>
|
|
input mixedb: {a: SInt<1>, b: const UInt<2>}
|
|
; CHECK: %vec: !firrtl.const.vector<uint<1>, 4>) {
|
|
input vec: const UInt<1>[4]
|
|
|
|
; CHECK-NEXT: %w = firrtl.wire interesting_name : !firrtl.const.sint<4>
|
|
wire w: const SInt<4>
|
|
; CHECK-NEXT: firrtl.matchingconnect %w, %s4 : !firrtl.const.sint<4>
|
|
connect w, s4
|
|
; CHECK-NEXT: %nonconst_w = firrtl.wire interesting_name : !firrtl.sint<4>
|
|
wire nonconst_w: SInt<4>
|
|
; CHECK-NEXT: [[CAST:%.+]] = firrtl.constCast %s4 : (!firrtl.const.sint<4>) -> !firrtl.sint<4>
|
|
; CHECK-NEXT: firrtl.matchingconnect %nonconst_w, [[CAST]] : !firrtl.sint<4>
|
|
connect nonconst_w, s4
|
|
|
|
;// -----
|
|
|
|
; CHECK-LABEL: firrtl.circuit "Foo_v3p0p0"
|
|
FIRRTL version 3.0.0
|
|
circuit Foo_v3p0p0:
|
|
module Foo_v3p0p0:
|
|
input clock: Clock
|
|
input reset: UInt<1>
|
|
input a: UInt<1>
|
|
output b: UInt<1>
|
|
|
|
; CHECK: firrtl.matchingconnect %b, %a
|
|
connect b, a
|
|
|
|
; CHECK: [[INV:%.+]] = firrtl.invalidvalue : !firrtl.uint<1>
|
|
; CHECK-NEXT: firrtl.matchingconnect %b, [[INV]] : !firrtl.uint<1>
|
|
invalidate b
|
|
|
|
; CHECK: %[[zero:[0-9A-Za-z_]+]] = firrtl.constant 0
|
|
; CHECK-NEXT: %r = firrtl.regreset interesting_name %clock, %reset, %[[zero]]
|
|
regreset r: UInt<1>, clock, reset, UInt<1>(0)
|
|
|
|
; CHECK: module private @LiteralIdentifiers
|
|
; CHECK-SAME: in %_0: !firrtl.bundle<"1": uint<1>>
|
|
; CHECK-SAME: out %_2: !firrtl.bundle<"3": uint<1>>
|
|
; CHECK-SAME: portNames = ["0", "2"]
|
|
module LiteralIdentifiers:
|
|
input `0`: {`1`: UInt<1>}
|
|
output `2`: {`3`: UInt<1>}
|
|
|
|
; CHECK-NEXT: %0 = firrtl.subfield %_0["1"] : !firrtl.bundle<"1": uint<1>>
|
|
; CHECK-NEXT: %1 = firrtl.subfield %_2["3"] : !firrtl.bundle<"3": uint<1>>
|
|
; CHECK-NEXT: firrtl.matchingconnect %1, %0 : !firrtl.uint<1>
|
|
connect `2`.`3`, `0`.`1`
|
|
|
|
; Ensure that `a` is equivalent to a.
|
|
; CHECK-NEXT: %a = firrtl.node {{.+}}%_0
|
|
node `a` = `0`
|
|
; CHECK-NEXT: %b = firrtl.node {{.+}}%a
|
|
node b = a
|
|
|
|
;// -----
|
|
; Check reference expressions using literal identifiers or keywords.
|
|
|
|
; CHECK-LABEL: firrtl.circuit "Probes_refexprs"
|
|
FIRRTL version 3.0.0
|
|
circuit Probes_refexprs:
|
|
extmodule refs:
|
|
output `0`: {`1`: Probe<{`2`: UInt<1>}>, rwprobe: RWProbe<UInt<1>>}
|
|
output ref: {module: Probe<{when: UInt<1>}>}
|
|
|
|
module Probes_refexprs:
|
|
output `0`: {`1`: Probe<{`2`: UInt<1>}>}
|
|
output out: UInt<1>
|
|
|
|
inst `9` of refs
|
|
inst ref of refs
|
|
|
|
; CHECK: firrtl.ref.define
|
|
define `0`.`1` = `9`.`0`.`1`
|
|
|
|
; CHECK-COUNT-4: firrtl.ref.resolve
|
|
node a = read(`9`.`0`.`1`).`2`
|
|
node b = read(`9`.`0`.`1`.`2`)
|
|
node c = read(`9`.ref.module).when
|
|
; Keyword as leading part of static ref expression:
|
|
node d = read(ref.`0`.`1`.`2`)
|
|
|
|
connect out, and(and(a, b), and(c, d))
|
|
|
|
; CHECK: %[[TEST:.+]] = firrtl.wire sym @[[TEST_SYM:[^ ]+]]
|
|
wire `test`: {`0`: UInt<1>, `b`: UInt<1>}
|
|
connect `test`.`0`, a
|
|
connect `test`.`b`, b
|
|
; CHECK: %[[TEST_REF:.+]] = firrtl.ref.rwprobe <@Probes_refexprs::@[[TEST_SYM]]>
|
|
; CHECK: force_initial %{{.+}}, %[[TEST_REF]], %[[TEST]]
|
|
force_initial(rwprobe(`test`), `test`)
|
|
; CHECK: force_initial
|
|
force_initial(`9`.`0`.rwprobe, `test`.`0`)
|
|
|
|
;// -----
|
|
|
|
; CHECK-LABEL: firrtl.circuit "RadixEncodedIntegerLiterals"
|
|
FIRRTL version 2.4.0
|
|
circuit RadixEncodedIntegerLiterals:
|
|
module RadixEncodedIntegerLiterals:
|
|
output bu: UInt<8>
|
|
output ou: UInt<8>
|
|
output du0: UInt<8>
|
|
output du1: UInt<8>
|
|
output hu: UInt<8>
|
|
output bs: SInt<8>
|
|
output os: SInt<8>
|
|
output dus0: SInt<8>
|
|
output dus1: SInt<8>
|
|
output hs: SInt<8>
|
|
|
|
; CHECK: %[[c42_ui7:[-a-zA-Z_0-9]+]] = firrtl.constant 42
|
|
; CHECK-NEXT: %[[c_constCast:[-a-zA-Z_0-9]+]] = firrtl.constCast %[[c42_ui7]]
|
|
; CHECK-NEXT: firrtl.connect %bu, %[[c_constCast]]
|
|
bu <= UInt(0b101010)
|
|
|
|
; CHECK-NEXT: %[[c_constCast:[-a-zA-Z_0-9]+]] = firrtl.constCast %[[c42_ui7]]
|
|
; CHECK-NEXT: firrtl.connect %ou, %[[c_constCast]]
|
|
ou <= UInt(0o052)
|
|
|
|
; Note: this creates a second constant because the width of a parsed
|
|
; constant is dependent on the overestimation of LLVM::StringRef.
|
|
;
|
|
; CHECK: %[[c42_ui8:[-a-zA-Z_0-9]+]] = firrtl.constant 42
|
|
; CHECK-NEXT: %[[c_constCast:[-a-zA-Z_0-9]+]] = firrtl.constCast %[[c42_ui8]]
|
|
; CHECK-NEXT: firrtl.connect %du0, %[[c_constCast]]
|
|
du0 <= UInt(42)
|
|
|
|
; CHECK-NEXT: %[[c_constCast:[-a-zA-Z_0-9]+]] = firrtl.constCast %[[c42_ui8]]
|
|
; CHECK-NEXT: firrtl.connect %du1, %[[c_constCast]]
|
|
du1 <= UInt(0d42)
|
|
|
|
; CHECK-NEXT: %[[c_constCast:[-a-zA-Z_0-9]+]] = firrtl.constCast %[[c42_ui7]]
|
|
; CHECK-NEXT: firrtl.connect %hu, %[[c_constCast]]
|
|
hu <= UInt(0h2a)
|
|
|
|
; CHECK: %[[cn42_si7:[-a-zA-Z_0-9]+]] = firrtl.constant -42
|
|
; CHECK-NEXT: %[[c_constCast:[-a-zA-Z_0-9]+]] = firrtl.constCast %[[cn42_si7]]
|
|
; CHECK-NEXT: firrtl.connect %bs, %[[c_constCast]]
|
|
bs <= SInt(-0b101010)
|
|
|
|
; CHECK-NEXT: %[[c_constCast:[-a-zA-Z_0-9]+]] = firrtl.constCast %[[cn42_si7]]
|
|
; CHECK-NEXT: firrtl.connect %os, %[[c_constCast]]
|
|
os <= SInt(-0o52)
|
|
|
|
; Note: this creates a second constant because the width of a parsed
|
|
; constant is dependent on the overestimation of LLVM::StringRef.
|
|
;
|
|
; CHECK: %[[cn42_si8:[-a-zA-Z_0-9]+]] = firrtl.constant -42
|
|
; CHECK-NEXT: %[[c_constCast:[-a-zA-Z_0-9]+]] = firrtl.constCast %[[cn42_si8]]
|
|
; CHECK-NEXT: firrtl.connect %dus0, %[[c_constCast]]
|
|
dus0 <= SInt(-42)
|
|
|
|
; CHECK-NEXT: %[[c_constCast:[-a-zA-Z_0-9]+]] = firrtl.constCast %[[cn42_si8]]
|
|
; CHECK-NEXT: firrtl.connect %dus1, %[[c_constCast]]
|
|
dus1 <= SInt(-0d42)
|
|
|
|
; CHECK-NEXT: %[[c_constCast:[-a-zA-Z_0-9]+]] = firrtl.constCast %[[cn42_si7]]
|
|
; CHECK-NEXT: firrtl.connect %hs, %[[c_constCast]]
|
|
hs <= SInt(-0h2a)
|
|
|
|
;// -----
|
|
; Tests for type alias
|
|
FIRRTL version 4.0.0
|
|
circuit Top:
|
|
type WordType = const UInt<32>
|
|
type ValidType = UInt<1>
|
|
type Data = {w: const WordType[2], valid: ValidType, flip ready: UInt<1>}
|
|
type Complex = { real: SInt<10>, imag: SInt<10> }
|
|
type Complex_id = Complex
|
|
; expected-warning @+1 {{type alias for non-base type '!firrtl.probe<alias<Complex, bundle<real: sint<10>, imag: sint<10>>>>' is currently not supported. Type alias is stripped immediately}}
|
|
type ProbeComplex = Probe<Complex>
|
|
; CHECK: @Top
|
|
; CHECK-SAME: in %in_data: !firrtl.alias<Data, bundle<w: const.vector<const.alias<WordType, const.uint<32>>, 2>,
|
|
; CHECK-SAME: valid: alias<ValidType, uint<1>>, ready flip: uint<1>>>,
|
|
; CHECK-SAME: in %in_complex: !firrtl.alias<Complex, bundle<real: sint<10>, imag: sint<10>>>
|
|
; CHECK-SAME: out %out: !firrtl.probe<alias<Complex, bundle<real: sint<10>, imag: sint<10>>>>
|
|
; CHECK-SAME: out %out_valid: !firrtl.alias<ValidType, uint<1>>
|
|
|
|
; CHECK-NEXT: %[[RESULT:.+]] = firrtl.subfield %in_data[valid] : !firrtl.alias<Data, bundle<w: const.vector<const.alias<WordType, const.uint<32>>, 2>, valid: alias<ValidType, uint<1>>, ready flip: uint<1>>>
|
|
; CHECK-NEXT: %c = firrtl.wire interesting_name : !firrtl.alias<Complex_id, alias<Complex, bundle<real: sint<10>, imag: sint<10>>>>
|
|
; CHECK-NEXT: firrtl.matchingconnect %out_valid, %[[RESULT]] : !firrtl.alias<ValidType, uint<1>>
|
|
public module Top:
|
|
input in_data: Data
|
|
input in_complex: Complex
|
|
output out: ProbeComplex
|
|
output out_valid: ValidType
|
|
wire c: Complex_id
|
|
connect out_valid, in_data.valid
|
|
|
|
; CHECK-LABEL: firrtl.module private @Const
|
|
; CHECK-SAME: (in %a: !firrtl.const.alias<ConstI1, const.uint<1>>)
|
|
type ConstI1 = const UInt<1>
|
|
module Const :
|
|
input a: ConstI1
|
|
|
|
;// -----
|
|
|
|
; CHECK-LABEL: firrtl.circuit "Layers"
|
|
FIRRTL version 4.0.0
|
|
circuit Layers:
|
|
layer A, bind:
|
|
layer B, bind:
|
|
layer C, bind:
|
|
layer D, bind:
|
|
layer E, inline:
|
|
layer F, bind:
|
|
; CHECK-NEXT: firrtl.layer @A bind {
|
|
; CHECK-NEXT: firrtl.layer @B bind {
|
|
; CHECK-NEXT: firrtl.layer @C bind {
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: firrtl.layer @D bind {
|
|
; CHECK-NEXT: firrtl.layer @E inline {
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: firrtl.layer @F bind {
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: }
|
|
|
|
; CHECK: firrtl.module @Layers
|
|
; CHECK-SAME: out %b: !firrtl.probe<uint<1>, @A>
|
|
; CHECK-SAME: out %c: !firrtl.rwprobe<uint<1>, @A::@B>
|
|
public module Layers:
|
|
input a: UInt<1>
|
|
output b: Probe<UInt<1>, A>
|
|
output c: RWProbe<UInt<1>, A.B>
|
|
|
|
layerblock A:
|
|
node A_a = a
|
|
layerblock B:
|
|
node B_a = a
|
|
layerblock C:
|
|
node C_a = a
|
|
layerblock D:
|
|
node D_a = a
|
|
layerblock E:
|
|
node E_a = a
|
|
layerblock F:
|
|
node F_a = a
|
|
|
|
; CHECK-NEXT: firrtl.layerblock @A {
|
|
; CHECK-NEXT: %A_a = firrtl.node{{.*}} %a
|
|
; CHECK-NEXT: firrtl.layerblock @A::@B {
|
|
; CHECK-NEXT: %B_a = firrtl.node{{.*}} %a
|
|
; CHECK-NEXT: firrtl.layerblock @A::@B::@C {
|
|
; CHECK-NEXT: %C_a = firrtl.node{{.*}} %a
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: firrtl.layerblock @A::@B::@D {
|
|
; CHECK-NEXT: %D_a = firrtl.node{{.*}} %a
|
|
; CHECK-NEXT: firrtl.layerblock @A::@B::@D::@E {
|
|
; CHECK-NEXT: %E_a = firrtl.node{{.*}} %a
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: firrtl.layerblock @A::@F {
|
|
; CHECK-NEXT: %F_a = firrtl.node{{.*}} %a
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: }
|
|
|
|
; CHECK: firrtl.layer @WithDirectory1 bind attributes {output_file = #hw.output_file<"foo{{/|\\\\}}">}
|
|
layer WithDirectory1, bind, "foo":
|
|
; CHECK: firrtl.layer @WithDirectory2 bind attributes {output_file = #hw.output_file<"foo{{/|\\\\}}">}
|
|
layer WithDirectory2, bind, "foo/":
|
|
|
|
;// -----
|
|
; CHECK-LABEL: firrtl.circuit "BasicProps"
|
|
FIRRTL version 3.3.0
|
|
circuit BasicProps :
|
|
module BasicProps :
|
|
; CHECK-LABEL: module private @Integer
|
|
module Integer :
|
|
; CHECK-SAME: out %a: !firrtl.integer
|
|
output a : Integer
|
|
; CHECK: %0 = firrtl.integer -10
|
|
; CHECK: firrtl.propassign %a, %0 : !firrtl.integer
|
|
propassign a, Integer(-10)
|
|
|
|
; CHECK-LABEL: module private @Bool
|
|
module Bool :
|
|
; CHECK-SAME: out %true: !firrtl.bool
|
|
; CHECK-SAME: out %false: !firrtl.bool
|
|
output true : Bool
|
|
output false : Bool
|
|
; CHECK-NEXT: %0 = firrtl.bool true
|
|
; CHECK-NEXT: firrtl.propassign %true, %0 : !firrtl.bool
|
|
; CHECK-NEXT: %1 = firrtl.bool false
|
|
; CHECK-NEXT: firrtl.propassign %false, %1 : !firrtl.bool
|
|
propassign true, Bool(true)
|
|
propassign false, Bool(false)
|
|
|
|
; CHECK-LABEL: module private @Double
|
|
module Double :
|
|
; CHECK-SAME: out %x: !firrtl.double
|
|
; CHECK-SAME: out %y: !firrtl.double
|
|
; CHECK-SAME: out %negzero: !firrtl.double
|
|
; CHECK-SAME: out %twoTo64: !firrtl.double
|
|
; CHECK-SAME: out %exp: !firrtl.double
|
|
output x : Double
|
|
output y : Double
|
|
output negzero : Double
|
|
output twoTo64 : Double
|
|
output exp : Double
|
|
; Try not to overly rely on double printing/rounding/precision.
|
|
; CHECK-NEXT: firrtl.double 0.1111111111111111 : f64
|
|
; CHECK: propassign
|
|
propassign x, Double(0.1111111111111111111111111111111111111111)
|
|
; CHECK: firrtl.double 1.{{0*[eE]}}+00
|
|
propassign y, Double(1.0)
|
|
; CHECK: firrtl.double -0.{{0+[eE]}}+00
|
|
propassign negzero, Double(-0.0)
|
|
; CHECK: firrtl.double 1.844674407370955{{[0-9]*[eE]}}+
|
|
propassign twoTo64, Double(18446744073709551616.0)
|
|
; CHECK: firrtl.double 1.2{{.+[eE]}}+30
|
|
propassign exp, Double(1.2E+30)
|
|
|
|
; CHECK-LABEL: module private @String
|
|
module String :
|
|
; CHECK-SAME: out %a: !firrtl.string
|
|
output a : String
|
|
; CHECK: %0 = firrtl.string "hello"
|
|
; CHECK: firrtl.propassign %a, %0 : !firrtl.string
|
|
propassign a, String("hello")
|
|
|
|
; CHECK-LABEL: module private @Path
|
|
module Path :
|
|
; CHECK-SAME: out %path: !firrtl.path
|
|
output path : Path
|
|
; CHECK: firrtl.unresolved_path "OMDeleted:"
|
|
; CHECK: firrtl.propassign %path, %0 : !firrtl.path
|
|
propassign path, path("OMDeleted:")
|
|
|
|
; CHECK-LABEL: firrtl.class private @SimpleClass(in %a: !firrtl.string, out %b: !firrtl.string) {
|
|
; CHECK-NEXT: firrtl.propassign %b, %a : !firrtl.string
|
|
; CHECK-NEXT: }
|
|
class SimpleClass:
|
|
input a: String
|
|
output b: String
|
|
propassign b, a
|
|
|
|
; CHECK-LABEL: firrtl.class private @Client(out %a: !firrtl.class<@SimpleClass(in a: !firrtl.string, out b: !firrtl.string)>)
|
|
class Client:
|
|
output a: Inst<SimpleClass>
|
|
; CHECK-NEXT: %b = firrtl.object @SimpleClass(in a: !firrtl.string, out b: !firrtl.string)
|
|
object b of SimpleClass
|
|
; CHECK-NEXT: firrtl.propassign %a, %b : !firrtl.class<@SimpleClass(in a: !firrtl.string, out b: !firrtl.string)>
|
|
propassign a, b
|
|
|
|
; CHECK-LABEL firrtl.class private @OtherClient(in %a: !firrtl.string, out %b: !firrtl.string)
|
|
class OtherClient:
|
|
input a : String
|
|
output b : String
|
|
object o of SimpleClass
|
|
; TODO: This test needs to be fixed up once flow-checking for objects is implemented correctly.
|
|
propassign b, o.b
|
|
|
|
; CHECK-LABEL firrtl.extclass private @ExtClass(in in: !firrtl.string, out out: !firrtl.string)
|
|
extclass ExtClass:
|
|
input in : String
|
|
output out : String
|
|
|
|
; CHECK-LABEL: firrtl.class private @UserOfExtClass(in %ext_object: !firrtl.class<@ExtClass(in in: !firrtl.string, out out: !firrtl.string)>, out %out: !firrtl.string)
|
|
class UserOfExtClass:
|
|
input ext_object : Inst<ExtClass>
|
|
output out : String
|
|
; CHECK-NEXT: %0 = firrtl.object.subfield %ext_object[out] : !firrtl.class<@ExtClass(in in: !firrtl.string, out out: !firrtl.string)
|
|
; CHECK-NEXT: firrtl.propassign %out, %0 : !firrtl.string
|
|
propassign out, ext_object.out
|
|
|
|
; CHECK-LABEL: module private @List
|
|
module List :
|
|
; CHECK-SAME: out %strings: !firrtl.list<string>
|
|
; CHECK-SAME: out %objs: !firrtl.list<class<@SimpleClass({{.*}})>>
|
|
; CHECK-SAME: out %nested: !firrtl.list<list<string>>
|
|
output strings : List<String>
|
|
output objs : List<Inst<SimpleClass>>
|
|
output nested : List<List<String>>
|
|
|
|
; CHECK-NEXT: %[[HELLO:.+]] = firrtl.string "hello"
|
|
; CHECK-NEXT: %[[WORLD:.+]] = firrtl.string "world"
|
|
; CHECK-NEXT: %[[STRINGS:.+]] = firrtl.list.create %[[HELLO]], %[[WORLD]] : !firrtl.list<string>
|
|
; CHECK-NEXT: firrtl.propassign %strings, %[[STRINGS]] : !firrtl.list<string>
|
|
propassign strings, List<String>(String("hello"), String("world"))
|
|
|
|
; CHECK-NEXT: %[[OBJ:.+]] = firrtl.object
|
|
; CHECK-NEXT: %[[OBJS:.+]] = firrtl.list.create %[[OBJ]], %[[OBJ]] : !firrtl.list<class<@SimpleClass({{.*}})>>
|
|
; CHECK-NEXT: firrtl.propassign %objs, %[[OBJS]] : !firrtl.list<class
|
|
object obj of SimpleClass
|
|
propassign objs, List<Inst<SimpleClass>>(obj, obj)
|
|
|
|
; CHECK-NEXT: %[[EMPTY1:.+]] = firrtl.list.create : !firrtl.list<string>
|
|
; CHECK-NEXT: %[[TEST:.+]] = firrtl.string "test"
|
|
; CHECK-NEXT: %[[TESTLIST:.+]] = firrtl.list.create %[[TEST]] : !firrtl.list<string>
|
|
; CHECK-NEXT: %[[EMPTY2:.+]] = firrtl.list.create : !firrtl.list<string>
|
|
; CHECK-NEXT: %[[NESTED:.+]] = firrtl.list.create %[[EMPTY1]], %[[TESTLIST]], %[[EMPTY2]] : !firrtl.list<list<string>>
|
|
; CHECK-NEXT: firrtl.propassign %nested, %[[NESTED]]
|
|
propassign nested, List<List<String>>(List<String>(), List<String>(String("test")), List<String>())
|
|
|
|
;// -----
|
|
FIRRTL version 4.0.0
|
|
|
|
; CHECK-LABEL: firrtl.circuit "IntegerArithmetic"
|
|
circuit IntegerArithmetic :
|
|
public module IntegerArithmetic :
|
|
input a : Integer
|
|
input b : Integer
|
|
output c : Integer
|
|
output d : Integer
|
|
output e : Integer
|
|
output f : Integer
|
|
|
|
; CHECK: [[C:%.+]] = firrtl.integer.add %a, %b
|
|
; CHECK: firrtl.propassign %c, [[C]]
|
|
propassign c, integer_add(a, b)
|
|
|
|
; CHECK: [[D:%.+]] = firrtl.integer.mul %a, %b
|
|
; CHECK: firrtl.propassign %d, [[D]]
|
|
propassign d, integer_mul(a, b)
|
|
|
|
; CHECK: [[E:%.+]] = firrtl.integer.shr %a, %b
|
|
; CHECK: firrtl.propassign %e, [[E]]
|
|
propassign e, integer_shr(a, b)
|
|
|
|
; CHECK: [[F:%.+]] = firrtl.integer.shl %a, %b
|
|
; CHECK: firrtl.propassign %f, [[F]]
|
|
propassign f, integer_shl(a, b)
|
|
|
|
;// -----
|
|
FIRRTL version 4.0.0
|
|
|
|
; CHECK-LABEL: firrtl.circuit "PropertyListOps"
|
|
circuit PropertyListOps :
|
|
public module PropertyListOps :
|
|
input a : List<Integer>
|
|
input b : List<Integer>
|
|
output c : List<Integer>
|
|
|
|
; CHECK: [[C:%.+]] = firrtl.list.concat %a, %b
|
|
; CHECK: firrtl.propassign %c, [[C]]
|
|
propassign c, list_concat(a, b)
|
|
|
|
;// -----
|
|
FIRRTL version 3.1.0
|
|
|
|
; CHECK-LABEL: circuit "BundleOfProps"
|
|
circuit BundleOfProps:
|
|
module BundleOfProps:
|
|
input x : {a : String}
|
|
wire y : {a: String}
|
|
; CHECK-COUNT-2: !firrtl.openbundle<a: string>
|
|
|
|
;// -----
|
|
FIRRTL version 3.1.0
|
|
|
|
; CHECK-LABEL: circuit "VecOfProps"
|
|
circuit VecOfProps:
|
|
module VecOfProps:
|
|
input x : String[2]
|
|
wire y : String[2]
|
|
; CHECK-COUNT-2: openvector<string, 2>
|
|
|
|
;// -----
|
|
; Test parsing of wires of probes, wires of agg of probes, and namekinds.
|
|
; CHECK-LABEL: circuit "WireOfProbesAndNames"
|
|
FIRRTL version 4.0.0
|
|
circuit WireOfProbesAndNames:
|
|
public module WireOfProbesAndNames:
|
|
; CHECK: %mixed = firrtl.wire interesting_name : !firrtl.openbundle
|
|
wire mixed : { a : UInt<3>, b : Probe<UInt<3>> }
|
|
; CHECK: %probe = firrtl.wire : !firrtl.probe
|
|
wire probe : Probe<UInt<1>>
|
|
|
|
;// -----
|
|
FIRRTL version 3.3.0
|
|
|
|
; CHECK-LABEL: circuit "AnyRef"
|
|
circuit AnyRef:
|
|
class Foo:
|
|
skip
|
|
module AnyRef:
|
|
input x : AnyRef
|
|
; CHECK: !firrtl.anyref
|
|
output y : AnyRef
|
|
; CHECK: !firrtl.anyref
|
|
output listOfAny : List<AnyRef>
|
|
; CHECK: !firrtl.list<anyref>
|
|
|
|
object foo of Foo
|
|
propassign y, foo
|
|
; CHECK: %[[OBJ:.+]] = firrtl.object
|
|
; CHECK: %[[CAST:.+]] = firrtl.object.anyref_cast %[[OBJ]]
|
|
; CHECK: firrtl.propassign %y, %[[CAST]]
|
|
|
|
propassign listOfAny, List<AnyRef>(foo, x)
|
|
; CHECK-NEXT: %[[CAST:.+]] = firrtl.object.anyref_cast %[[OBJ]]
|
|
; CHECK-NEXT: %[[LIST:.+]] = firrtl.list.create %[[CAST]], %x
|
|
; CHECK-NEXT: propassign %listOfAny, %[[LIST]]
|
|
|
|
;// -----
|
|
|
|
FIRRTL version 4.0.0
|
|
; CHECK-LABEL: circuit "PublicModules"
|
|
circuit PublicModules:
|
|
; CHECK: firrtl.module @Foo
|
|
public module Foo:
|
|
; CHECK: firrtl.module private @Bar
|
|
module Bar:
|
|
; CHECK: firrtl.module @PublicModules
|
|
public module PublicModules:
|
|
|
|
;// -----
|
|
|
|
FIRRTL version 4.0.0
|
|
; CHECK-LABEL: firrtl.circuit "LayerEnabledModule"
|
|
circuit LayerEnabledModule:
|
|
layer A, bind:
|
|
layer B, bind:
|
|
layer C, bind:
|
|
; CHECK: firrtl.module @LayerEnabledModule
|
|
; CHECK-SAME: layers = [@A, @B::@C]
|
|
public module LayerEnabledModule enablelayer A enablelayer B.C:
|
|
|
|
; CHECK: firrtl.module private @UserOfLayerEnabledModule
|
|
; CHECK-SAME: layers = [@A, @B::@C]
|
|
module UserOfLayerEnabledModule enablelayer A enablelayer B.C:
|
|
; CHECK: firrtl.instance i interesting_name {layers = [@A, @B::@C]} @LayerEnabledModule()
|
|
inst i of LayerEnabledModule
|
|
|
|
;// -----
|
|
|
|
FIRRTL version 3.3.0
|
|
; CHECK-LABEL: circuit "StaticShiftRight"
|
|
circuit StaticShiftRight:
|
|
; CHECK: firrtl.module @StaticShiftRight
|
|
module StaticShiftRight:
|
|
input a : UInt<8>
|
|
input b : UInt<0>
|
|
input c : SInt<8>
|
|
input d : SInt<0>
|
|
|
|
wire w : UInt
|
|
connect w, a
|
|
|
|
wire x : SInt
|
|
connect x, c
|
|
|
|
; CHECK: %0 = firrtl.shr %a, 1
|
|
; CHECK: %1 = firrtl.pad %0, 1
|
|
; CHECK: %a_1 = firrtl.node {{.*}} %1 : !firrtl.uint<7>
|
|
node a_1 = shr(a, 1)
|
|
; CHECK: %2 = firrtl.shr %a, 8
|
|
; CHECK: %3 = firrtl.pad %2, 1
|
|
; CHECK: %a_2 = firrtl.node {{.*}} %3 : !firrtl.uint<1>
|
|
node a_2 = shr(a, 8)
|
|
; CHECK: %4 = firrtl.shr %a, 10
|
|
; CHECK: %5 = firrtl.pad %4, 1
|
|
; CHECK: %a_3 = firrtl.node {{.*}} %5 : !firrtl.uint<1>
|
|
node a_3 = shr(a, 10)
|
|
; CHECK: %6 = firrtl.shr %b, 0
|
|
; CHECK: %7 = firrtl.pad %6, 1
|
|
; CHECK: %b_1 = firrtl.node {{.*}} %7 : !firrtl.uint<1>
|
|
node b_1 = shr(b, 0)
|
|
; CHECK: %8 = firrtl.shr %b, 1
|
|
; CHECK: %9 = firrtl.pad %8, 1
|
|
; CHECK: %b_2 = firrtl.node {{.*}} %9 : !firrtl.uint<1>
|
|
node b_2 = shr(b, 1)
|
|
; CHECK: %10 = firrtl.shr %w, 10
|
|
; CHECK: %11 = firrtl.pad %10, 1
|
|
; CHECK: %w_1 = firrtl.node {{.*}} %11 : !firrtl.uint
|
|
node w_1 = shr(w, 10)
|
|
|
|
; CHECK: %12 = firrtl.shr %c, 1
|
|
; CHECK: %c_1 = firrtl.node {{.*}} %12 : !firrtl.sint<7>
|
|
node c_1 = shr(c, 1)
|
|
; CHECK: %13 = firrtl.shr %c, 8
|
|
; CHECK: %c_2 = firrtl.node {{.*}} %13 : !firrtl.sint<1>
|
|
node c_2 = shr(c, 8)
|
|
; CHECK: %14 = firrtl.shr %c, 10
|
|
; CHECK: %c_3 = firrtl.node {{.*}} %14 : !firrtl.sint<1>
|
|
node c_3 = shr(c, 10)
|
|
; CHECK: %15 = firrtl.shr %d, 0
|
|
; CHECK: %d_1 = firrtl.node {{.*}} %15 : !firrtl.sint<1>
|
|
node d_1 = shr(d, 0)
|
|
; CHECK: %16 = firrtl.shr %d, 1
|
|
; CHECK: %d_2 = firrtl.node {{.*}} %16 : !firrtl.sint<1>
|
|
node d_2 = shr(d, 1)
|
|
; CHECK: %17 = firrtl.shr %x, 10
|
|
; CHECK: %x_1 = firrtl.node {{.*}} %17 : !firrtl.sint
|
|
node x_1 = shr(x, 10)
|
|
|
|
;// -----
|
|
|
|
FIRRTL version 4.0.0
|
|
; CHECK-LABEL: circuit "StaticShiftRight"
|
|
circuit StaticShiftRight:
|
|
; CHECK: firrtl.module @StaticShiftRight
|
|
public module StaticShiftRight:
|
|
input a : UInt<8>
|
|
input b : UInt<0>
|
|
input c : SInt<8>
|
|
input d : SInt<0>
|
|
|
|
wire w : UInt
|
|
connect w, a
|
|
|
|
wire x : SInt
|
|
connect x, c
|
|
|
|
; CHECK: %0 = firrtl.shr %a, 1
|
|
; CHECK: %a_1 = firrtl.node {{.*}} %0 : !firrtl.uint<7>
|
|
node a_1 = shr(a, 1)
|
|
; CHECK: %1 = firrtl.shr %a, 8
|
|
; CHECK: %a_2 = firrtl.node {{.*}} %1 : !firrtl.uint<0>
|
|
node a_2 = shr(a, 8)
|
|
; CHECK: %2 = firrtl.shr %a, 10
|
|
; CHECK: %a_3 = firrtl.node {{.*}} %2 : !firrtl.uint<0>
|
|
node a_3 = shr(a, 10)
|
|
; CHECK: %3 = firrtl.shr %b, 0
|
|
; CHECK: %b_1 = firrtl.node {{.*}} %3 : !firrtl.uint<0>
|
|
node b_1 = shr(b, 0)
|
|
; CHECK: %4 = firrtl.shr %b, 1
|
|
; CHECK: %b_2 = firrtl.node {{.*}} %4 : !firrtl.uint<0>
|
|
node b_2 = shr(b, 1)
|
|
; CHECK: %5 = firrtl.shr %w, 10
|
|
; CHECK: %w_1 = firrtl.node {{.*}} %5 : !firrtl.uint
|
|
node w_1 = shr(w, 10)
|
|
|
|
; CHECK: %6 = firrtl.shr %c, 1
|
|
; CHECK: %c_1 = firrtl.node {{.*}} %6 : !firrtl.sint<7>
|
|
node c_1 = shr(c, 1)
|
|
; CHECK: %7 = firrtl.shr %c, 8
|
|
; CHECK: %c_2 = firrtl.node {{.*}} %7 : !firrtl.sint<1>
|
|
node c_2 = shr(c, 8)
|
|
; CHECK: %8 = firrtl.shr %c, 10
|
|
; CHECK: %c_3 = firrtl.node {{.*}} %8 : !firrtl.sint<1>
|
|
node c_3 = shr(c, 10)
|
|
; CHECK: %9 = firrtl.shr %d, 0
|
|
; CHECK: %d_1 = firrtl.node {{.*}} %9 : !firrtl.sint<1>
|
|
node d_1 = shr(d, 0)
|
|
; CHECK: %10 = firrtl.shr %d, 1
|
|
; CHECK: %d_2 = firrtl.node {{.*}} %10 : !firrtl.sint<1>
|
|
node d_2 = shr(d, 1)
|
|
; CHECK: %11 = firrtl.shr %x, 10
|
|
; CHECK: %x_1 = firrtl.node {{.*}} %11 : !firrtl.sint
|
|
node x_1 = shr(x, 10)
|
|
|
|
;// -----
|
|
FIRRTL version 4.0.0
|
|
; CHECK-LABEL: circuit "GenericIntrinsics"
|
|
circuit GenericIntrinsics:
|
|
; CHECK: firrtl.module @GenericIntrinsics
|
|
public module GenericIntrinsics:
|
|
input clock : Clock
|
|
input data : UInt<32>
|
|
input c : UInt<1>
|
|
|
|
; Statements
|
|
; CHECK-NEXT: firrtl.int.generic "circt_verif_assert" %c : (!firrtl.uint<1>) -> ()
|
|
intrinsic(circt_verif_assert, c)
|
|
; CHECK-NEXT: firrtl.int.generic "circt_fpga_probe" %data, %clock : (!firrtl.uint<32>, !firrtl.clock) -> ()
|
|
intrinsic(circt_fpga_probe, data, clock)
|
|
|
|
; Expressions
|
|
; CHECK-NEXT: %[[PAV:.+]] = firrtl.int.generic "circt_plusargs_value" <FORMAT: none = "foo"> : () -> !firrtl.bundle<found: uint<1>, result: uint<5>>
|
|
; CHECK-NEXT: %n = firrtl.node interesting_name %[[PAV]]
|
|
node n = intrinsic(circt_plusargs_value<FORMAT = "foo"> : { found : UInt<1>, result : UInt<5> })
|
|
; CHECK-NEXT: %[[PAT:.+]] = firrtl.int.generic "circt_plusargs_test" <FORMAT: none = "bar"> : () -> !firrtl.uint<1>
|
|
; CHECK-NEXT: %n2 = firrtl.node interesting_name %[[PAT]]
|
|
node n2 = intrinsic(circt_plusargs_test<FORMAT = "bar"> : UInt<1>)
|
|
|
|
|
|
; Statement with unused return value.
|
|
; CHECK-NEXT: firrtl.int.generic "circt_clock_gate" %clock, %c : (!firrtl.clock, !firrtl.uint<1>) -> !firrtl.clock
|
|
intrinsic(circt_clock_gate : Clock, clock, c)
|
|
|
|
; CHECK-NEXT: %[[SZ:.+]] = firrtl.int.generic "circt_isX"
|
|
; CHECK-NEXT: "circt_verif_assert" %[[SZ]]
|
|
intrinsic(circt_verif_assert, intrinsic(circt_isX: UInt<1>, data))
|
|
|
|
;// -----
|
|
FIRRTL version 4.0.0
|
|
; CHECK-LABEL: circuit "Foo"
|
|
circuit Foo:
|
|
|
|
; CHECK-LABEL: firrtl.module @Foo(in %data: !firrtl.uint<32>, in %c: !firrtl.uint<1>, out %out: !firrtl.uint<32>)
|
|
public module Foo:
|
|
input data : UInt<32>
|
|
input c : UInt<1>
|
|
output out : UInt<32>
|
|
|
|
when c:
|
|
node add1 = add(data, UInt<32>(1))
|
|
connect out, add1
|
|
else:
|
|
connect out, data
|
|
|
|
; CHECK-LABEL: firrtl.module @FooTest(in %s_foo_c: !firrtl.uint<1>, in %s_foo_data: !firrtl.uint<32>)
|
|
public module FooTest:
|
|
input s_foo_c : UInt<1>
|
|
input s_foo_data : UInt<32>
|
|
|
|
; CHECK-NEXT: %foo_data, %foo_c, %foo_out = firrtl.instance foo interesting_name @Foo(in data: !firrtl.uint<32>, in c: !firrtl.uint<1>, out out: !firrtl.uint<32>)
|
|
inst foo of Foo
|
|
; CHECK-NEXT: firrtl.matchingconnect %foo_c, %s_foo_c : !firrtl.uint<1>
|
|
connect foo.c, s_foo_c
|
|
; CHECK-NEXT: firrtl.matchingconnect %foo_data, %s_foo_data : !firrtl.uint<32>
|
|
connect foo.data, s_foo_data
|
|
; CHECK-NEXT: %0 = firrtl.eq %foo_out, %s_foo_data : (!firrtl.uint<32>, !firrtl.uint<32>) -> !firrtl.uint<1>
|
|
; CHECK-NEXT: %1 = firrtl.int.generic "circt_ltl_implication" %s_foo_c, %0 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
|
|
; CHECK-NEXT: firrtl.int.generic "circt_verif_assert" %1 : (!firrtl.uint<1>) -> ()
|
|
intrinsic(circt_verif_assert, intrinsic(circt_ltl_implication : UInt<1>, s_foo_c, eq(foo.out, s_foo_data)))
|
|
|
|
; CHECK: firrtl.formal @testFormal of @FooTest bound 20
|
|
formal testFormal of FooTest, bound = 20
|
|
|
|
;// -----
|
|
FIRRTL version 3.9.0
|
|
circuit Foo:
|
|
|
|
; CHECK-LABEL: firrtl.extmodule private @Bar(in in: !firrtl.uint)
|
|
extmodule Bar:
|
|
input in: UInt
|
|
|
|
; CHECK-LABEL: firrtl.intmodule private @MyIntModule(in in: !firrtl.uint, out out: !firrtl.uint<8>)
|
|
; CHECK: attributes {intrinsic = "testIntrinsic1"}
|
|
; CHECK-NOT: {
|
|
intmodule MyIntModule :
|
|
input in: UInt
|
|
output out: UInt<8>
|
|
intrinsic = testIntrinsic1
|
|
|
|
; CHECK-LABEL: firrtl.intmodule private @MyParameterizedIntModule
|
|
; CHECK-SAME: <FORMAT: none = "xyz_timeout=%d\0A",
|
|
; CHECK-SAME: DEFAULT: ui32 = 0,
|
|
; CHECK-SAME: WIDTH: ui32 = 32,
|
|
; CHECK-SAME: DEPTH: f64 = 3.242000e+01>
|
|
; CHECK-SAME: (in in: !firrtl.uint,
|
|
; CHECK-SAME: out out: !firrtl.uint<8>)
|
|
; CHECK-SAME: attributes {intrinsic = "testIntrinsic2"}
|
|
; CHECK-NOT: {
|
|
intmodule MyParameterizedIntModule :
|
|
input in: UInt
|
|
output out: UInt<8>
|
|
intrinsic = testIntrinsic2
|
|
parameter FORMAT = "xyz_timeout=%d\n"
|
|
parameter DEFAULT = 0
|
|
parameter WIDTH = 32
|
|
parameter DEPTH = 32.42
|
|
|
|
; CHECK-LABEL: extmodule private @RefExt(
|
|
; CHECK-SAME: in in: !firrtl.uint<1>, out r: !firrtl.probe<uint<1>>
|
|
; CHECK-SAME: internalPaths = [#firrtl.internalpath, #firrtl.internalpath<"in">]
|
|
extmodule RefExt :
|
|
input in : UInt<1>
|
|
output r : Probe<UInt<1>>
|
|
ref r is "in"
|
|
|
|
; CHECK-LABEL: extmodule private @RefExtMore(
|
|
; CHECK-SAME: in in: !firrtl.uint<1>
|
|
; CHECK-SAME: out r: !firrtl.probe<uint<1>>
|
|
; CHECK-SAME: out data: !firrtl.uint<3>
|
|
; CHECK-SAME: out r2: !firrtl.probe<vector<bundle<a: uint<3>>, 3>>
|
|
; CHECK-SAME: internalPaths = [#firrtl.internalpath, #firrtl.internalpath<"path.to.internal.signal">, #firrtl.internalpath, #firrtl.internalpath<"in">]
|
|
extmodule RefExtMore :
|
|
input in : UInt<1>
|
|
output r : Probe<UInt<1>>
|
|
output data : UInt<3>
|
|
output r2 : Probe<{a : UInt<3>}[3]>
|
|
ref r2 is "in"
|
|
ref r is "path.to.internal.signal"
|
|
|
|
; CHECK-LABEL: module @Foo(
|
|
; CHECK-SAME: out %out: !firrtl.uint,
|
|
module Foo:
|
|
output out: UInt
|
|
output out3 : UInt<3>
|
|
|
|
; CHECK: %{{.+}}, %[[REM_R:.+]], %{{.+}}, %[[REM_R2:.+]] = firrtl.instance rem
|
|
; CHECK-NEXT: %[[REM_R2_1:.+]] = firrtl.ref.sub %[[REM_R2]][1]
|
|
; CHECK-NEXT: %[[REM_R2_1_A:.+]] = firrtl.ref.sub %[[REM_R2_1]][0]
|
|
; CHECK-NEXT: %[[READ_REM_R2_1_A:.+]] = firrtl.ref.resolve %[[REM_R2_1_A]]
|
|
; CHECK-NEXT: connect %out3, %[[READ_REM_R2_1_A]]
|
|
inst rem of RefExtMore
|
|
connect out3, read(rem.r2[1].a)
|
|
|
|
;// -----
|
|
FIRRTL version 2.9.0
|
|
circuit Foo:
|
|
module Bar:
|
|
input a: UInt<1>
|
|
|
|
module Foo:
|
|
input a: UInt<1>
|
|
output b: UInt<1>
|
|
|
|
node binary = UInt<4>("b1010")
|
|
node octal = UInt<4>("o12")
|
|
node decimal = UInt<4>(10)
|
|
node hexadecimal = UInt<4>("ha")
|
|
|
|
inst bar of Bar
|
|
bar is invalid
|
|
|
|
b <= a
|