1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
|
// See LICENSE for license details.
import chisel3.core.CompileOptions
/** The chisel3 package contains the chisel3 API.
* It maps core components into the public chisel3 namespace.
*/
package object chisel3 { // scalastyle:ignore package.object.name
import scala.language.implicitConversions
import internal.firrtl.Width
import util.BitPat
import chisel3.util._
import chisel3.internal.chiselRuntimeDeprecated
import chisel3.internal.firrtl.Port
import chisel3.core.CompileOptions
val Input = chisel3.core.Input
val Output = chisel3.core.Output
val Flipped = chisel3.core.Flipped
val chiselTypeOf = chisel3.core.chiselTypeOf
type Data = chisel3.core.Data
object Wire extends chisel3.core.WireFactory {
import chisel3.core.CompileOptions
@chiselRuntimeDeprecated
@deprecated("Wire(init=init) is deprecated, use WireDefault(init) instead", "chisel3")
def apply[T <: Data](dummy: Int = 0, init: T)(implicit compileOptions: CompileOptions): T =
chisel3.core.WireDefault(init)
@chiselRuntimeDeprecated
@deprecated("Wire(t, init) is deprecated, use WireDefault(t, init) instead", "chisel3")
def apply[T <: Data](t: T, init: T)(implicit compileOptions: CompileOptions): T =
chisel3.core.WireDefault(t, init)
@chiselRuntimeDeprecated
@deprecated("Wire(t, init) is deprecated, use WireDefault(t, init) instead", "chisel3")
def apply[T <: Data](t: T, init: DontCare.type)(implicit compileOptions: CompileOptions): T =
chisel3.core.WireDefault(t, init)
}
val WireInit = chisel3.core.WireDefault
val WireDefault = chisel3.core.WireDefault
val Clock = chisel3.core.Clock
type Clock = chisel3.core.Clock
// Clock and reset scoping functions
val withClockAndReset = chisel3.core.withClockAndReset
val withClock = chisel3.core.withClock
val withReset = chisel3.core.withReset
implicit class AddDirectionToData[T<:Data](target: T) {
@chiselRuntimeDeprecated
@deprecated("Input(Data) should be used over Data.asInput", "chisel3")
def asInput: T = Input(target)
@chiselRuntimeDeprecated
@deprecated("Output(Data) should be used over Data.asOutput", "chisel3")
def asOutput: T = Output(target)
@chiselRuntimeDeprecated
@deprecated("Flipped(Data) should be used over Data.flip", "chisel3")
def flip(): T = Flipped(target)
}
implicit class fromBitsable[T <: Data](data: T) {
import chisel3.core.CompileOptions
import chisel3.internal.sourceinfo.SourceInfo
@chiselRuntimeDeprecated
@deprecated("fromBits is deprecated, use asTypeOf instead", "chisel3")
def fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
that.asTypeOf(data)
}
}
implicit class cloneTypeable[T <: Data](target: T) {
@chiselRuntimeDeprecated
@deprecated("chiselCloneType is deprecated, use chiselTypeOf(...) to get the Chisel Type of a hardware object", "chisel3") // scalastyle:ignore line.size.limit
def chiselCloneType: T = {
target.cloneTypeFull.asInstanceOf[T]
}
}
type Aggregate = chisel3.core.Aggregate
object Vec extends chisel3.core.VecFactory {
import scala.language.experimental.macros
import chisel3.core.CompileOptions
import chisel3.internal.sourceinfo._
@chiselRuntimeDeprecated
@deprecated("Vec argument order should be size, t; this will be removed by the official release", "chisel3")
def apply[T <: Data](gen: T, n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] =
apply(n, gen)
@chiselRuntimeDeprecated
@deprecated("Vec.fill(n)(gen) is deprecated, use VecInit(Seq.fill(n)(gen)) instead", "chisel3")
def fill[T <: Data](n: Int)(gen: => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] =
apply(Seq.fill(n)(gen))
def apply[T <: Data](elts: Seq[T]): Vec[T] = macro VecTransform.apply_elts
@chiselRuntimeDeprecated
@deprecated("Vec(elts) is deprecated, use VecInit(elts) instead", "chisel3")
def do_apply[T <: Data](elts: Seq[T])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] =
chisel3.core.VecInit(elts)
def apply[T <: Data](elt0: T, elts: T*): Vec[T] = macro VecTransform.apply_elt0
@chiselRuntimeDeprecated
@deprecated("Vec(elt0, ...) is deprecated, use VecInit(elt0, ...) instead", "chisel3")
def do_apply[T <: Data](elt0: T, elts: T*)
(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] =
chisel3.core.VecInit(elt0 +: elts.toSeq)
def tabulate[T <: Data](n: Int)(gen: (Int) => T): Vec[T] = macro VecTransform.tabulate
@chiselRuntimeDeprecated
@deprecated("Vec.tabulate(n)(gen) is deprecated, use VecInit.tabulate(n)(gen) instead", "chisel3")
def do_tabulate[T <: Data](n: Int)(gen: (Int) => T)
(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] =
chisel3.core.VecInit.tabulate(n)(gen)
}
val VecInit = chisel3.core.VecInit
type Vec[T <: Data] = chisel3.core.Vec[T]
type VecLike[T <: Data] = chisel3.core.VecLike[T]
type Bundle = chisel3.core.Bundle
type IgnoreSeqInBundle = chisel3.core.IgnoreSeqInBundle
type Record = chisel3.core.Record
val assert = chisel3.core.assert
type Element = chisel3.core.Element
type Bits = chisel3.core.Bits
// Some possible regex replacements for the literal specifier deprecation:
// (note: these are not guaranteed to handle all edge cases! check all replacements!)
// Bool\((true|false)\)
// => $1.B
// UInt\(width\s*=\s*(\d+|[_a-zA-Z][_0-9a-zA-Z]*)\)
// => UInt($1.W)
// (UInt|SInt|Bits).width\((\d+|[_a-zA-Z][_0-9a-zA-Z]*)\)
// => $1($2.W)
// (U|S)Int\((-?\d+|0[xX][0-9a-fA-F]+)\)
// => $2.$1
// UInt\((\d+|0[xX][0-9a-fA-F]+),\s*(?:width\s*=)?\s*(\d+|[_a-zA-Z][_0-9a-zA-Z]*)\)
// => $1.U($2.W)
// (UInt|SInt|Bool)\(([_a-zA-Z][_0-9a-zA-Z]*)\)
// => $2.as$1
// (UInt|SInt)\(([_a-zA-Z][_0-9a-zA-Z]*),\s*(?:width\s*=)?\s*(\d+|[_a-zA-Z][_0-9a-zA-Z]*)\)
// => $2.as$1($3.W)
/** This contains literal constructor factory methods that are deprecated as of Chisel3.
* These will be removed very soon. It's recommended you port your code ASAP.
*/
trait UIntFactory extends chisel3.core.UIntFactory {
/** Create a UInt literal with inferred width. */
@chiselRuntimeDeprecated
@deprecated("use n.U", "chisel3, will be removed by end of 2017")
def apply(n: String): UInt = n.asUInt
/** Create a UInt literal with fixed width. */
@chiselRuntimeDeprecated
@deprecated("use n.U(width.W)", "chisel3, will be removed by end of 2017")
def apply(n: String, width: Int): UInt = n.asUInt(width.W)
/** Create a UInt literal with specified width. */
@chiselRuntimeDeprecated
@deprecated("use value.U(width)", "chisel3, will be removed by end of 2017")
def apply(value: BigInt, width: Width): UInt = value.asUInt(width)
/** Create a UInt literal with fixed width. */
@chiselRuntimeDeprecated
@deprecated("use value.U(width.W)", "chisel3, will be removed by end of 2017")
def apply(value: BigInt, width: Int): UInt = value.asUInt(width.W)
/** Create a UInt literal with inferred width.- compatibility with Chisel2. */
@chiselRuntimeDeprecated
@deprecated("use value.U", "chisel3, will be removed by end of 2017")
def apply(value: BigInt): UInt = value.asUInt
/** Create a UInt with a specified width */
@chiselRuntimeDeprecated
@deprecated("use UInt(width.W)", "chisel3, will be removed by end of 2017")
def width(width: Int): UInt = apply(width.W)
/** Create a UInt port with specified width. */
@chiselRuntimeDeprecated
@deprecated("use UInt(width)", "chisel3, will be removed by end of 2017")
def width(width: Width): UInt = apply(width)
}
/** This contains literal constructor factory methods that are deprecated as of Chisel3.
* These will be removed very soon. It's recommended you move your code soon.
*/
trait SIntFactory extends chisel3.core.SIntFactory {
/** Create a SInt type or port with fixed width. */
@chiselRuntimeDeprecated
@deprecated("use SInt(width.W)", "chisel3, will be removed by end of 2017")
def width(width: Int): SInt = apply(width.W)
/** Create an SInt type with specified width. */
@chiselRuntimeDeprecated
@deprecated("use SInt(width)", "chisel3, will be removed by end of 2017")
def width(width: Width): SInt = apply(width)
/** Create an SInt literal with inferred width. */
@chiselRuntimeDeprecated
@deprecated("use value.S", "chisel3, will be removed by end of 2017")
def apply(value: BigInt): SInt = value.asSInt
/** Create an SInt literal with fixed width. */
@chiselRuntimeDeprecated
@deprecated("use value.S(width.W)", "chisel3, will be removed by end of 2017")
def apply(value: BigInt, width: Int): SInt = value.asSInt(width.W)
/** Create an SInt literal with specified width. */
@chiselRuntimeDeprecated
@deprecated("use value.S(width)", "chisel3, will be removed by end of 2017")
def apply(value: BigInt, width: Width): SInt = value.asSInt(width)
@chiselRuntimeDeprecated
@deprecated("use value.S", "chisel3, will be removed by end of 2017")
def Lit(value: BigInt): SInt = value.asSInt // scalastyle:ignore method.name
@chiselRuntimeDeprecated
@deprecated("use value.S(width)", "chisel3, will be removed by end of 2017")
def Lit(value: BigInt, width: Int): SInt = value.asSInt(width.W) // scalastyle:ignore method.name
}
/** This contains literal constructor factory methods that are deprecated as of Chisel3.
* These will be removed very soon. It's recommended you move your code soon.
*/
trait BoolFactory extends chisel3.core.BoolFactory {
/** Creates Bool literal.
*/
@chiselRuntimeDeprecated
@deprecated("use x.B", "chisel3, will be removed by end of 2017")
def apply(x: Boolean): Bool = x.B
}
object Bits extends UIntFactory
type Num[T <: Data] = chisel3.core.Num[T]
type UInt = chisel3.core.UInt
object UInt extends UIntFactory
type SInt = chisel3.core.SInt
object SInt extends SIntFactory
type Bool = chisel3.core.Bool
object Bool extends BoolFactory
val Mux = chisel3.core.Mux
type BlackBox = chisel3.core.BlackBox
type InstanceId = chisel3.internal.InstanceId
val Mem = chisel3.core.Mem
type MemBase[T <: Data] = chisel3.core.MemBase[T]
type Mem[T <: Data] = chisel3.core.Mem[T]
val SyncReadMem = chisel3.core.SyncReadMem
type SyncReadMem[T <: Data] = chisel3.core.SyncReadMem[T]
@deprecated("Use 'SyncReadMem'", "chisel3")
val SeqMem = chisel3.core.SyncReadMem
@deprecated("Use 'SyncReadMem'", "chisel3")
type SeqMem[T <: Data] = chisel3.core.SyncReadMem[T]
val Module = chisel3.core.Module
type Module = chisel3.core.LegacyModule
val printf = chisel3.core.printf
val RegNext = chisel3.core.RegNext
val RegInit = chisel3.core.RegInit
object Reg {
import chisel3.core.{Binding, CompileOptions}
import chisel3.internal.sourceinfo.SourceInfo
import chisel3.internal.throwException
// Passthrough for chisel3.core.Reg
// TODO: make val Reg = chisel3.core.Reg once we eliminate the legacy Reg constructor
def apply[T <: Data](t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T =
chisel3.core.Reg(t)
@chiselRuntimeDeprecated
@deprecated("Use Reg(t), RegNext(next, [init]) or RegInit([t], init) instead", "chisel3")
def apply[T <: Data](t: T = null, next: T = null, init: T = null)
(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
if (t ne null) {
val reg = if (init ne null) {
RegInit(t, init)
} else {
chisel3.core.Reg(t)
}
if (next ne null) {
reg := next
}
reg
} else if (next ne null) {
if (init ne null) {
RegNext(next, init)
} else {
RegNext(next)
}
} else if (init ne null) {
RegInit(init)
} else {
throwException("cannot infer type")
}
}
}
val when = chisel3.core.when
type WhenContext = chisel3.core.WhenContext
type Printable = chisel3.core.Printable
val Printable = chisel3.core.Printable
type Printables = chisel3.core.Printables
val Printables = chisel3.core.Printables
type PString = chisel3.core.PString
val PString = chisel3.core.PString
type FirrtlFormat = chisel3.core.FirrtlFormat
val FirrtlFormat = chisel3.core.FirrtlFormat
type Decimal = chisel3.core.Decimal
val Decimal = chisel3.core.Decimal
type Hexadecimal = chisel3.core.Hexadecimal
val Hexadecimal = chisel3.core.Hexadecimal
type Binary = chisel3.core.Binary
val Binary = chisel3.core.Binary
type Character = chisel3.core.Character
val Character = chisel3.core.Character
type Name = chisel3.core.Name
val Name = chisel3.core.Name
type FullName = chisel3.core.FullName
val FullName = chisel3.core.FullName
val Percent = chisel3.core.Percent
/** Implicit for custom Printable string interpolator */
implicit class PrintableHelper(val sc: StringContext) extends AnyVal {
/** Custom string interpolator for generating Printables: p"..."
* Will call .toString on any non-Printable arguments (mimicking s"...")
*/
def p(args: Any*): Printable = {
sc.checkLengths(args) // Enforce sc.parts.size == pargs.size + 1
val pargs: Seq[Option[Printable]] = args map {
case p: Printable => Some(p)
case d: Data => Some(d.toPrintable)
case any => for {
v <- Option(any) // Handle null inputs
str = v.toString
if !str.isEmpty // Handle empty Strings
} yield PString(str)
}
val parts = sc.parts map StringContext.treatEscapes
// Zip sc.parts and pargs together ito flat Seq
// eg. Seq(sc.parts(0), pargs(0), sc.parts(1), pargs(1), ...)
val seq = for { // append None because sc.parts.size == pargs.size + 1
(literal, arg) <- parts zip (pargs :+ None)
optPable <- Seq(Some(PString(literal)), arg)
pable <- optPable // Remove Option[_]
} yield pable
Printables(seq)
}
}
implicit def string2Printable(str: String): Printable = PString(str)
implicit class fromBigIntToLiteral(x: BigInt) extends chisel3.core.fromBigIntToLiteral(x)
implicit class fromtIntToLiteral(x: Int) extends chisel3.core.fromIntToLiteral(x)
implicit class fromtLongToLiteral(x: Long) extends chisel3.core.fromLongToLiteral(x)
implicit class fromStringToLiteral(x: String) extends chisel3.core.fromStringToLiteral(x)
implicit class fromBooleanToLiteral(x: Boolean) extends chisel3.core.fromBooleanToLiteral(x)
implicit class fromDoubleToLiteral(x: Double) extends chisel3.core.fromDoubleToLiteral(x)
implicit class fromIntToWidth(x: Int) extends chisel3.core.fromIntToWidth(x)
implicit class fromIntToBinaryPoint(x: Int) extends chisel3.core.fromIntToBinaryPoint(x)
implicit class fromUIntToBitPatComparable(x: UInt) extends chisel3.SourceInfoDoc {
import scala.language.experimental.macros
import internal.sourceinfo.{SourceInfo, SourceInfoTransform}
final def === (that: BitPat): Bool = macro SourceInfoTransform.thatArg
final def =/= (that: BitPat): Bool = macro SourceInfoTransform.thatArg
/** @group SourceInfoTransformMacro */
def do_=== (that: BitPat) // scalastyle:ignore method.name
(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that === x
/** @group SourceInfoTransformMacro */
def do_=/= (that: BitPat) // scalastyle:ignore method.name
(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that =/= x
final def != (that: BitPat): Bool = macro SourceInfoTransform.thatArg
@chiselRuntimeDeprecated
@deprecated("Use '=/=', which avoids potential precedence problems", "chisel3")
def do_!= (that: BitPat) // scalastyle:ignore method.name
(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that != x
}
type ChiselException = chisel3.internal.ChiselException
// Debugger/Tester access to internal Chisel data structures and methods.
def getDataElements(a: Aggregate): Seq[Element] = {
a.allElements
}
def getModulePorts(m: Module): Seq[Port] = m.getPorts
// Invalidate API - a DontCare element for explicit assignment to outputs,
// indicating the signal is intentionally not driven.
val DontCare = chisel3.core.DontCare
/** Package for experimental features, which may have their API changed, be removed, etc.
*
* Because its contents won't necessarily have the same level of stability and support as
* non-experimental, you must explicitly import this package to use its contents.
*/
object experimental { // scalastyle:ignore object.name
type Param = chisel3.core.Param
type IntParam = chisel3.core.IntParam
val IntParam = chisel3.core.IntParam
type DoubleParam = chisel3.core.DoubleParam
val DoubleParam = chisel3.core.DoubleParam
type StringParam = chisel3.core.StringParam
val StringParam = chisel3.core.StringParam
type RawParam = chisel3.core.RawParam
val RawParam = chisel3.core.RawParam
type Analog = chisel3.core.Analog
val Analog = chisel3.core.Analog
val attach = chisel3.core.attach
type ChiselEnum = chisel3.core.EnumFactory
val EnumAnnotations = chisel3.core.EnumAnnotations
@deprecated("Use the version in chisel3._", "chisel3.2")
val withClockAndReset = chisel3.core.withClockAndReset
@deprecated("Use the version in chisel3._", "chisel3.2")
val withClock = chisel3.core.withClock
@deprecated("Use the version in chisel3._", "chisel3.2")
val withReset = chisel3.core.withReset
val dontTouch = chisel3.core.dontTouch
val doNotDedup = chisel3.core.doNotDedup
type BaseModule = chisel3.core.BaseModule
type RawModule = chisel3.core.RawModule
type MultiIOModule = chisel3.core.MultiIOModule
type ExtModule = chisel3.core.ExtModule
val IO = chisel3.core.IO
// Rocket Chip-style clonemodule
/** A record containing the results of CloneModuleAsRecord
* The apply method is retrieves the element with the supplied name.
*/
type ClonePorts = chisel3.core.BaseModule.ClonePorts
object CloneModuleAsRecord {
/** Clones an existing module and returns a record of all its top-level ports.
* Each element of the record is named with a string matching the
* corresponding port's name and shares the port's type.
* @example {{{
* val q1 = Module(new Queue(UInt(32.W), 2))
* val q2_io = CloneModuleAsRecord(q1)("io").asInstanceOf[q1.io.type]
* q2_io.enq <> q1.io.deq
* }}}
*/
def apply(proto: BaseModule)(implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, compileOptions: chisel3.core.CompileOptions): ClonePorts = { // scalastyle:ignore line.size.limit
chisel3.core.BaseModule.cloneIORecord(proto)
}
}
// Implicit conversions for BlackBox Parameters
implicit def fromIntToIntParam(x: Int): IntParam = IntParam(BigInt(x))
implicit def fromLongToIntParam(x: Long): IntParam = IntParam(BigInt(x))
implicit def fromBigIntToIntParam(x: BigInt): IntParam = IntParam(x)
implicit def fromDoubleToDoubleParam(x: Double): DoubleParam = DoubleParam(x)
implicit def fromStringToStringParam(x: String): StringParam = StringParam(x)
// Fixed Point is experimental for now
type FixedPoint = chisel3.core.FixedPoint
val FixedPoint = chisel3.core.FixedPoint
type ChiselAnnotation = chisel3.core.ChiselAnnotation
val ChiselAnnotation = chisel3.core.ChiselAnnotation
type RunFirrtlTransform = chisel3.core.RunFirrtlTransform
val annotate = chisel3.core.annotate
val DataMirror = chisel3.core.DataMirror
val requireIsHardware = chisel3.core.requireIsHardware
val requireIsChiselType = chisel3.core.requireIsChiselType
type Direction = chisel3.core.ActualDirection
val Direction = chisel3.core.ActualDirection
implicit class ChiselRange(val sc: StringContext) extends AnyVal {
import scala.language.experimental.macros
import internal.firrtl.NumericBound
/** Specifies a range using mathematical range notation. Variables can be interpolated using
* standard string interpolation syntax.
* @example {{{
* UInt(range"[0, 2)")
* UInt(range"[0, \$myInt)")
* UInt(range"[0, \${myInt + 2})")
* }}}
*/
def range(args: Any*): (NumericBound[Int], NumericBound[Int]) = macro chisel3.internal.RangeTransform.apply
}
import scala.annotation.compileTimeOnly
class dump extends chisel3.internal.naming.dump // scalastyle:ignore class.name
class treedump extends chisel3.internal.naming.treedump // scalastyle:ignore class.name
class chiselName extends chisel3.internal.naming.chiselName // scalastyle:ignore class.name
object BundleLiterals {
implicit class AddBundleLiteralConstructor[T <: Bundle](x: T) {
def Lit(elems: (T => (Data, Data))*): T = {
x._makeLit(elems: _*)
}
}
}
}
}
|